├── Nat.idr ├── README.md └── contributing.md /Nat.idr: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- This file is here so GitHub thinks this is an Idris repo :D 3 | -------------------------------------------------------------------------------- 4 | 5 | module Prelude.Nat 6 | 7 | import Builtins 8 | 9 | import Prelude.Algebra 10 | import Prelude.Basics 11 | import Prelude.Bool 12 | import Prelude.Cast 13 | import Prelude.Interfaces 14 | import Prelude.Uninhabited 15 | 16 | %access public export 17 | %default total 18 | 19 | ||| Natural numbers: unbounded, unsigned integers which can be pattern 20 | ||| matched. 21 | %elim data Nat = 22 | ||| Zero 23 | Z | 24 | ||| Successor 25 | S Nat 26 | 27 | -- name hints for interactive editing 28 | %name Nat k,j,i,n,m 29 | 30 | Uninhabited (Z = S n) where 31 | uninhabited Refl impossible 32 | 33 | -------------------------------------------------------------------------------- 34 | -- Syntactic tests 35 | -------------------------------------------------------------------------------- 36 | 37 | total isZero : Nat -> Bool 38 | isZero Z = True 39 | isZero (S n) = False 40 | 41 | total isSucc : Nat -> Bool 42 | isSucc Z = False 43 | isSucc (S n) = True 44 | 45 | -------------------------------------------------------------------------------- 46 | -- Basic arithmetic functions 47 | -------------------------------------------------------------------------------- 48 | 49 | ||| Add two natural numbers. 50 | ||| @ n the number to case-split on 51 | ||| @ m the other number 52 | total plus : (n, m : Nat) -> Nat 53 | plus Z right = right 54 | plus (S left) right = S (plus left right) 55 | 56 | ||| Multiply natural numbers 57 | total mult : Nat -> Nat -> Nat 58 | mult Z right = Z 59 | mult (S left) right = plus right $ mult left right 60 | 61 | ||| Convert an Integer to a Nat, mapping negative numbers to 0 62 | fromIntegerNat : Integer -> Nat 63 | fromIntegerNat 0 = Z 64 | fromIntegerNat n = 65 | if (n > 0) then 66 | S (fromIntegerNat (assert_smaller n (n - 1))) 67 | else 68 | Z 69 | 70 | ||| Convert a Nat to an Integer 71 | toIntegerNat : Nat -> Integer 72 | toIntegerNat Z = 0 73 | toIntegerNat (S k) = 1 + toIntegerNat k 74 | 75 | ||| Subtract natural numbers. If the second number is larger than the first, return 0. 76 | total minus : Nat -> Nat -> Nat 77 | minus Z right = Z 78 | minus left Z = left 79 | minus (S left) (S right) = minus left right 80 | 81 | ||| Exponentiation of natural numbers 82 | total power : Nat -> Nat -> Nat 83 | power base Z = S Z 84 | power base (S exp) = mult base $ power base exp 85 | 86 | hyper : Nat -> Nat -> Nat -> Nat 87 | hyper Z a b = S b 88 | hyper (S Z) a Z = a 89 | hyper (S(S Z)) a Z = Z 90 | hyper n a Z = S Z 91 | hyper (S pn) a (S pb) = hyper pn a (hyper (S pn) a pb) 92 | 93 | 94 | -------------------------------------------------------------------------------- 95 | -- Comparisons 96 | -------------------------------------------------------------------------------- 97 | 98 | ||| Proofs that `n` or `m` is not equal to Z 99 | data NotBothZero : (n, m : Nat) -> Type where 100 | LeftIsNotZero : NotBothZero (S n) m 101 | RightIsNotZero : NotBothZero n (S m) 102 | 103 | 104 | ||| Proofs that `n` is less than or equal to `m` 105 | ||| @ n the smaller number 106 | ||| @ m the larger number 107 | data LTE : (n, m : Nat) -> Type where 108 | ||| Zero is the smallest Nat 109 | LTEZero : LTE Z right 110 | ||| If n <= m, then n + 1 <= m + 1 111 | LTESucc : LTE left right -> LTE (S left) (S right) 112 | 113 | Uninhabited (LTE (S n) Z) where 114 | uninhabited LTEZero impossible 115 | 116 | ||| Greater than or equal to 117 | total GTE : Nat -> Nat -> Type 118 | GTE left right = LTE right left 119 | 120 | ||| Strict less than 121 | total LT : Nat -> Nat -> Type 122 | LT left right = LTE (S left) right 123 | 124 | ||| Strict greater than 125 | total GT : Nat -> Nat -> Type 126 | GT left right = LT right left 127 | 128 | ||| A successor is never less than or equal zero 129 | succNotLTEzero : Not (S m `LTE` Z) 130 | succNotLTEzero LTEZero impossible 131 | 132 | ||| If two numbers are ordered, their predecessors are too 133 | fromLteSucc : (S m `LTE` S n) -> (m `LTE` n) 134 | fromLteSucc (LTESucc x) = x 135 | 136 | ||| A decision procedure for `LTE` 137 | isLTE : (m, n : Nat) -> Dec (m `LTE` n) 138 | isLTE Z n = Yes LTEZero 139 | isLTE (S k) Z = No succNotLTEzero 140 | isLTE (S k) (S j) with (isLTE k j) 141 | isLTE (S k) (S j) | (Yes prf) = Yes (LTESucc prf) 142 | isLTE (S k) (S j) | (No contra) = No (contra . fromLteSucc) 143 | 144 | ||| `LTE` is reflexive. 145 | lteRefl : LTE n n 146 | lteRefl {n = Z} = LTEZero 147 | lteRefl {n = S k} = LTESucc lteRefl 148 | 149 | ||| n < m implies n < m + 1 150 | lteSuccRight : LTE n m -> LTE n (S m) 151 | lteSuccRight LTEZero = LTEZero 152 | lteSuccRight (LTESucc x) = LTESucc (lteSuccRight x) 153 | 154 | ||| n + 1 < m implies n < m 155 | lteSuccLeft : LTE (S n) m -> LTE n m 156 | lteSuccLeft (LTESucc x) = lteSuccRight x 157 | 158 | ||| `LTE` is transitive 159 | lteTransitive : LTE n m -> LTE m p -> LTE n p 160 | lteTransitive LTEZero y = LTEZero 161 | lteTransitive (LTESucc x) (LTESucc y) = LTESucc (lteTransitive x y) 162 | 163 | lteAddRight : (n : Nat) -> LTE n (plus n m) 164 | lteAddRight Z = LTEZero 165 | lteAddRight (S k) = LTESucc (lteAddRight k) 166 | 167 | 168 | ||| Boolean test than one Nat is less than or equal to another 169 | total lte : Nat -> Nat -> Bool 170 | lte Z right = True 171 | lte left Z = False 172 | lte (S left) (S right) = lte left right 173 | 174 | ||| Boolean test than one Nat is greater than or equal to another 175 | total gte : Nat -> Nat -> Bool 176 | gte left right = lte right left 177 | 178 | ||| Boolean test than one Nat is strictly less than another 179 | total lt : Nat -> Nat -> Bool 180 | lt left right = lte (S left) right 181 | 182 | ||| Boolean test than one Nat is strictly greater than another 183 | total gt : Nat -> Nat -> Bool 184 | gt left right = lt right left 185 | 186 | ||| Find the least of two natural numbers 187 | total minimum : Nat -> Nat -> Nat 188 | minimum Z m = Z 189 | minimum (S n) Z = Z 190 | minimum (S n) (S m) = S (minimum n m) 191 | 192 | ||| Find the greatest of two natural numbers 193 | total maximum : Nat -> Nat -> Nat 194 | maximum Z m = m 195 | maximum (S n) Z = S n 196 | maximum (S n) (S m) = S (maximum n m) 197 | 198 | ||| Cast Nat to Int 199 | ||| Note that this can overflow 200 | toIntNat : Nat -> Int 201 | toIntNat n = prim__truncBigInt_Int (toIntegerNat n) 202 | 203 | (-) : (m : Nat) -> (n : Nat) -> {auto smaller : LTE n m} -> Nat 204 | (-) m n {smaller} = minus m n 205 | 206 | -------------------------------------------------------------------------------- 207 | -- Interface implementations 208 | -------------------------------------------------------------------------------- 209 | 210 | Eq Nat where 211 | Z == Z = True 212 | (S l) == (S r) = l == r 213 | _ == _ = False 214 | 215 | Cast Nat Integer where 216 | cast = toIntegerNat 217 | 218 | Ord Nat where 219 | compare Z Z = EQ 220 | compare Z (S k) = LT 221 | compare (S k) Z = GT 222 | compare (S x) (S y) = compare x y 223 | 224 | Num Nat where 225 | (+) = plus 226 | (*) = mult 227 | 228 | fromInteger = fromIntegerNat 229 | 230 | MinBound Nat where 231 | minBound = Z 232 | 233 | ||| Casts negative `Integers` to 0. 234 | Cast Integer Nat where 235 | cast = fromInteger 236 | 237 | Cast String Nat where 238 | cast str = cast (the Integer (cast str)) 239 | 240 | ||| A wrapper for Nat that specifies the semigroup and monoid implementations that use (*) 241 | record Multiplicative where 242 | constructor GetMultiplicative 243 | _ : Nat 244 | 245 | ||| A wrapper for Nat that specifies the semigroup and monoid implementations that use (+) 246 | record Additive where 247 | constructor GetAdditive 248 | _ : Nat 249 | 250 | Semigroup Multiplicative where 251 | (<+>) left right = GetMultiplicative $ left' * right' 252 | where 253 | left' : Nat 254 | left' = 255 | case left of 256 | GetMultiplicative m => m 257 | 258 | right' : Nat 259 | right' = 260 | case right of 261 | GetMultiplicative m => m 262 | 263 | Semigroup Additive where 264 | left <+> right = GetAdditive $ left' + right' 265 | where 266 | left' : Nat 267 | left' = 268 | case left of 269 | GetAdditive m => m 270 | 271 | right' : Nat 272 | right' = 273 | case right of 274 | GetAdditive m => m 275 | 276 | Monoid Multiplicative where 277 | neutral = GetMultiplicative $ S Z 278 | 279 | Monoid Additive where 280 | neutral = GetAdditive Z 281 | 282 | ||| Casts negative `Ints` to 0. 283 | Cast Int Nat where 284 | cast i = fromInteger (cast i) 285 | 286 | Cast Nat Int where 287 | cast = toIntNat 288 | 289 | Cast Nat Double where 290 | cast = cast . toIntegerNat 291 | 292 | -------------------------------------------------------------------------------- 293 | -- Auxilliary notions 294 | -------------------------------------------------------------------------------- 295 | 296 | ||| The predecessor of a natural number. `pred Z` is `Z`. 297 | total pred : Nat -> Nat 298 | pred Z = Z 299 | pred (S n) = n 300 | 301 | -------------------------------------------------------------------------------- 302 | -- Fibonacci and factorial 303 | -------------------------------------------------------------------------------- 304 | 305 | ||| Fibonacci numbers 306 | total fib : Nat -> Nat 307 | fib Z = Z 308 | fib (S Z) = S Z 309 | fib (S (S n)) = fib (S n) + fib n 310 | 311 | ||| Factorial function 312 | total fact : Nat -> Nat 313 | fact Z = S Z 314 | fact (S n) = (S n) * fact n 315 | 316 | -------------------------------------------------------------------------------- 317 | -- Division and modulus 318 | -------------------------------------------------------------------------------- 319 | 320 | ||| The proof that no successor of a natural number can be zero. 321 | ||| 322 | ||| ```idris example 323 | ||| modNatNZ 10 3 SIsNotZ 324 | ||| ``` 325 | SIsNotZ : {x: Nat} -> (S x = Z) -> Void 326 | SIsNotZ Refl impossible 327 | 328 | ||| Modulus function where the divisor is not zero. 329 | ||| 330 | ||| ```idris example 331 | ||| modNatNZ 100 2 SIsNotZ 332 | ||| ``` 333 | modNatNZ : Nat -> (y: Nat) -> Not (y = Z) -> Nat 334 | modNatNZ left Z p = void (p Refl) 335 | modNatNZ left (S right) _ = mod' left left right 336 | where 337 | total mod' : Nat -> Nat -> Nat -> Nat 338 | mod' Z centre right = centre 339 | mod' (S left) centre right = 340 | if lte centre right then 341 | centre 342 | else 343 | mod' left (minus centre (S right)) right 344 | 345 | partial 346 | modNat : Nat -> Nat -> Nat 347 | modNat left (S right) = modNatNZ left (S right) SIsNotZ 348 | 349 | ||| Division where the divisor is not zero. 350 | ||| 351 | ||| ```idris example 352 | ||| divNatNZ 100 2 SIsNotZ 353 | ||| ``` 354 | divNatNZ : Nat -> (y: Nat) -> Not (y = Z) -> Nat 355 | divNatNZ left Z p = void (p Refl) 356 | divNatNZ left (S right) _ = div' left left right 357 | where 358 | total div' : Nat -> Nat -> Nat -> Nat 359 | div' Z centre right = Z 360 | div' (S left) centre right = 361 | if lte centre right then 362 | Z 363 | else 364 | S (div' left (minus centre (S right)) right) 365 | 366 | partial 367 | divNat : Nat -> Nat -> Nat 368 | divNat left (S right) = divNatNZ left (S right) SIsNotZ 369 | 370 | divCeilNZ : Nat -> (y: Nat) -> Not (y = 0) -> Nat 371 | divCeilNZ x y p = case (modNatNZ x y p) of 372 | Z => divNatNZ x y p 373 | S _ => S (divNatNZ x y p) 374 | 375 | partial 376 | divCeil : Nat -> Nat -> Nat 377 | divCeil x (S y) = divCeilNZ x (S y) SIsNotZ 378 | 379 | partial 380 | Integral Nat where 381 | div = divNat 382 | mod = modNat 383 | 384 | log2NZ : (x: Nat) -> Not (x = Z) -> Nat 385 | log2NZ Z p = void (p Refl) 386 | log2NZ (S Z) _ = Z 387 | log2NZ (S (S n)) _ = S (log2NZ (assert_smaller (S (S n)) (S (divNatNZ n 2 SIsNotZ))) SIsNotZ) 388 | 389 | partial 390 | log2 : Nat -> Nat 391 | log2 (S n) = log2NZ (S n) SIsNotZ 392 | 393 | -------------------------------------------------------------------------------- 394 | -- GCD and LCM 395 | -------------------------------------------------------------------------------- 396 | gcd : (a: Nat) -> (b: Nat) -> .{auto ok: NotBothZero a b} -> Nat 397 | gcd a Z = a 398 | gcd Z b = b 399 | gcd a (S b) = assert_total $ gcd (S b) (modNatNZ a (S b) SIsNotZ) 400 | 401 | lcm : Nat -> Nat -> Nat 402 | lcm _ Z = Z 403 | lcm Z _ = Z 404 | lcm a (S b) = assert_total $ divNat (a * (S b)) (gcd a (S b)) 405 | 406 | 407 | -------------------------------------------------------------------------------- 408 | -- An informative comparison view 409 | -------------------------------------------------------------------------------- 410 | data CmpNat : Nat -> Nat -> Type where 411 | CmpLT : (y : _) -> CmpNat x (x + S y) 412 | CmpEQ : CmpNat x x 413 | CmpGT : (x : _) -> CmpNat (y + S x) y 414 | 415 | total cmp : (x, y : Nat) -> CmpNat x y 416 | cmp Z Z = CmpEQ 417 | cmp Z (S k) = CmpLT _ 418 | cmp (S k) Z = CmpGT _ 419 | cmp (S x) (S y) with (cmp x y) 420 | cmp (S x) (S (x + (S k))) | CmpLT k = CmpLT k 421 | cmp (S x) (S x) | CmpEQ = CmpEQ 422 | cmp (S (y + (S k))) (S y) | CmpGT k = CmpGT k 423 | 424 | -------------------------------------------------------------------------------- 425 | -- Properties 426 | -------------------------------------------------------------------------------- 427 | 428 | -- Succ 429 | 430 | ||| S preserves equality 431 | total eqSucc : (left : Nat) -> (right : Nat) -> (p : left = right) -> 432 | S left = S right 433 | eqSucc left _ Refl = Refl 434 | 435 | ||| S is injective 436 | total succInjective : (left : Nat) -> (right : Nat) -> (p : S left = S right) -> 437 | left = right 438 | succInjective left _ Refl = Refl 439 | 440 | -- Plus 441 | total plusZeroLeftNeutral : (right : Nat) -> 0 + right = right 442 | plusZeroLeftNeutral right = Refl 443 | 444 | total plusZeroRightNeutral : (left : Nat) -> left + 0 = left 445 | plusZeroRightNeutral Z = Refl 446 | plusZeroRightNeutral (S n) = 447 | let inductiveHypothesis = plusZeroRightNeutral n in 448 | rewrite inductiveHypothesis in Refl 449 | 450 | total plusSuccRightSucc : (left : Nat) -> (right : Nat) -> 451 | S (left + right) = left + (S right) 452 | plusSuccRightSucc Z right = Refl 453 | plusSuccRightSucc (S left) right = 454 | let inductiveHypothesis = plusSuccRightSucc left right in 455 | rewrite inductiveHypothesis in Refl 456 | 457 | total plusCommutative : (left : Nat) -> (right : Nat) -> 458 | left + right = right + left 459 | plusCommutative Z right = rewrite plusZeroRightNeutral right in Refl 460 | plusCommutative (S left) right = 461 | let inductiveHypothesis = plusCommutative left right in 462 | rewrite inductiveHypothesis in 463 | rewrite plusSuccRightSucc right left in Refl 464 | 465 | total plusAssociative : (left : Nat) -> (centre : Nat) -> (right : Nat) -> 466 | left + (centre + right) = (left + centre) + right 467 | plusAssociative Z centre right = Refl 468 | plusAssociative (S left) centre right = 469 | let inductiveHypothesis = plusAssociative left centre right in 470 | rewrite inductiveHypothesis in Refl 471 | 472 | total plusConstantRight : (left : Nat) -> (right : Nat) -> (c : Nat) -> 473 | (p : left = right) -> left + c = right + c 474 | plusConstantRight left _ c Refl = Refl 475 | 476 | total plusConstantLeft : (left : Nat) -> (right : Nat) -> (c : Nat) -> 477 | (p : left = right) -> c + left = c + right 478 | plusConstantLeft left _ c Refl = Refl 479 | 480 | total plusOneSucc : (right : Nat) -> 1 + right = S right 481 | plusOneSucc n = Refl 482 | 483 | total plusLeftCancel : (left : Nat) -> (right : Nat) -> (right' : Nat) -> 484 | (p : left + right = left + right') -> right = right' 485 | plusLeftCancel Z right right' p = p 486 | plusLeftCancel (S left) right right' p = 487 | let inductiveHypothesis = plusLeftCancel left right right' in 488 | inductiveHypothesis (succInjective _ _ p) 489 | 490 | total plusRightCancel : (left : Nat) -> (left' : Nat) -> (right : Nat) -> 491 | (p : left + right = left' + right) -> left = left' 492 | plusRightCancel left left' Z p = rewrite sym (plusZeroRightNeutral left) in 493 | rewrite sym (plusZeroRightNeutral left') in 494 | p 495 | plusRightCancel left left' (S right) p = 496 | plusRightCancel left left' right 497 | (succInjective _ _ (rewrite plusSuccRightSucc left right in 498 | rewrite plusSuccRightSucc left' right in p)) 499 | 500 | total plusLeftLeftRightZero : (left : Nat) -> (right : Nat) -> 501 | (p : left + right = left) -> right = Z 502 | plusLeftLeftRightZero Z right p = p 503 | plusLeftLeftRightZero (S left) right p = 504 | plusLeftLeftRightZero left right (succInjective _ _ p) 505 | 506 | -- Mult 507 | total multZeroLeftZero : (right : Nat) -> Z * right = Z 508 | multZeroLeftZero right = Refl 509 | 510 | total multZeroRightZero : (left : Nat) -> left * Z = Z 511 | multZeroRightZero Z = Refl 512 | multZeroRightZero (S left) = multZeroRightZero left 513 | 514 | total multRightSuccPlus : (left : Nat) -> (right : Nat) -> 515 | left * (S right) = left + (left * right) 516 | multRightSuccPlus Z right = Refl 517 | multRightSuccPlus (S left) right = 518 | let inductiveHypothesis = multRightSuccPlus left right in 519 | rewrite inductiveHypothesis in 520 | rewrite plusAssociative left right (mult left right) in 521 | rewrite plusAssociative right left (mult left right) in 522 | rewrite plusCommutative right left in 523 | Refl 524 | 525 | total multLeftSuccPlus : (left : Nat) -> (right : Nat) -> 526 | (S left) * right = right + (left * right) 527 | multLeftSuccPlus left right = Refl 528 | 529 | total multCommutative : (left : Nat) -> (right : Nat) -> 530 | left * right = right * left 531 | multCommutative Z right = rewrite multZeroRightZero right in Refl 532 | multCommutative (S left) right = 533 | let inductiveHypothesis = multCommutative left right in 534 | rewrite inductiveHypothesis in 535 | rewrite multRightSuccPlus right left in 536 | Refl 537 | 538 | total multDistributesOverPlusRight : (left : Nat) -> (centre : Nat) -> (right : Nat) -> 539 | left * (centre + right) = (left * centre) + (left * right) 540 | multDistributesOverPlusRight Z centre right = Refl 541 | multDistributesOverPlusRight (S left) centre right = 542 | let inductiveHypothesis = multDistributesOverPlusRight left centre right in 543 | rewrite inductiveHypothesis in 544 | rewrite plusAssociative (plus centre (mult left centre)) right (mult left right) in 545 | rewrite sym (plusAssociative centre (mult left centre) right) in 546 | rewrite plusCommutative (mult left centre) right in 547 | rewrite plusAssociative centre right (mult left centre) in 548 | rewrite plusAssociative (plus centre right) (mult left centre) (mult left right) in 549 | Refl 550 | 551 | total multDistributesOverPlusLeft : (left : Nat) -> (centre : Nat) -> (right : Nat) -> 552 | (left + centre) * right = (left * right) + (centre * right) 553 | multDistributesOverPlusLeft Z centre right = Refl 554 | multDistributesOverPlusLeft (S left) centre right = 555 | let inductiveHypothesis = multDistributesOverPlusLeft left centre right in 556 | rewrite inductiveHypothesis in 557 | rewrite plusAssociative right (mult left right) (mult centre right) in 558 | Refl 559 | 560 | total multAssociative : (left : Nat) -> (centre : Nat) -> (right : Nat) -> 561 | left * (centre * right) = (left * centre) * right 562 | multAssociative Z centre right = Refl 563 | multAssociative (S left) centre right = 564 | let inductiveHypothesis = multAssociative left centre right in 565 | rewrite inductiveHypothesis in 566 | rewrite multDistributesOverPlusLeft centre (mult left centre) right in 567 | Refl 568 | 569 | total multOneLeftNeutral : (right : Nat) -> 1 * right = right 570 | multOneLeftNeutral Z = Refl 571 | multOneLeftNeutral (S right) = 572 | let inductiveHypothesis = multOneLeftNeutral right in 573 | rewrite inductiveHypothesis in 574 | Refl 575 | 576 | total multOneRightNeutral : (left : Nat) -> left * 1 = left 577 | multOneRightNeutral Z = Refl 578 | multOneRightNeutral (S left) = 579 | let inductiveHypothesis = multOneRightNeutral left in 580 | rewrite inductiveHypothesis in 581 | Refl 582 | 583 | -- Minus 584 | total minusSuccSucc : (left : Nat) -> (right : Nat) -> 585 | minus (S left) (S right) = minus left right 586 | minusSuccSucc left right = Refl 587 | 588 | total minusZeroLeft : (right : Nat) -> minus 0 right = Z 589 | minusZeroLeft right = Refl 590 | 591 | total minusZeroRight : (left : Nat) -> minus left 0 = left 592 | minusZeroRight Z = Refl 593 | minusZeroRight (S left) = Refl 594 | 595 | total minusZeroN : (n : Nat) -> Z = minus n n 596 | minusZeroN Z = Refl 597 | minusZeroN (S n) = minusZeroN n 598 | 599 | total minusOneSuccN : (n : Nat) -> S Z = minus (S n) n 600 | minusOneSuccN Z = Refl 601 | minusOneSuccN (S n) = minusOneSuccN n 602 | 603 | total minusSuccOne : (n : Nat) -> minus (S n) 1 = n 604 | minusSuccOne Z = Refl 605 | minusSuccOne (S n) = Refl 606 | 607 | total minusPlusZero : (n : Nat) -> (m : Nat) -> minus n (n + m) = Z 608 | minusPlusZero Z m = Refl 609 | minusPlusZero (S n) m = minusPlusZero n m 610 | 611 | total minusMinusMinusPlus : (left : Nat) -> (centre : Nat) -> (right : Nat) -> 612 | minus (minus left centre) right = minus left (centre + right) 613 | minusMinusMinusPlus Z Z right = Refl 614 | minusMinusMinusPlus (S left) Z right = Refl 615 | minusMinusMinusPlus Z (S centre) right = Refl 616 | minusMinusMinusPlus (S left) (S centre) right = 617 | let inductiveHypothesis = minusMinusMinusPlus left centre right in 618 | rewrite inductiveHypothesis in 619 | Refl 620 | 621 | total plusMinusLeftCancel : (left : Nat) -> (right : Nat) -> (right' : Nat) -> 622 | minus (left + right) (left + right') = minus right right' 623 | plusMinusLeftCancel Z right right' = Refl 624 | plusMinusLeftCancel (S left) right right' = 625 | let inductiveHypothesis = plusMinusLeftCancel left right right' in 626 | rewrite inductiveHypothesis in 627 | Refl 628 | 629 | total multDistributesOverMinusLeft : (left : Nat) -> (centre : Nat) -> (right : Nat) -> 630 | (minus left centre) * right = minus (left * right) (centre * right) 631 | multDistributesOverMinusLeft Z Z right = Refl 632 | multDistributesOverMinusLeft (S left) Z right = 633 | rewrite (minusZeroRight (plus right (mult left right))) in Refl 634 | multDistributesOverMinusLeft Z (S centre) right = Refl 635 | multDistributesOverMinusLeft (S left) (S centre) right = 636 | let inductiveHypothesis = multDistributesOverMinusLeft left centre right in 637 | rewrite inductiveHypothesis in 638 | rewrite plusMinusLeftCancel right (mult left right) (mult centre right) in 639 | Refl 640 | 641 | total multDistributesOverMinusRight : (left : Nat) -> (centre : Nat) -> (right : Nat) -> 642 | left * (minus centre right) = minus (left * centre) (left * right) 643 | multDistributesOverMinusRight left centre right = 644 | rewrite multCommutative left (minus centre right) in 645 | rewrite multDistributesOverMinusLeft centre right left in 646 | rewrite multCommutative centre left in 647 | rewrite multCommutative right left in 648 | Refl 649 | 650 | -- Power 651 | total powerSuccPowerLeft : (base : Nat) -> (exp : Nat) -> power base (S exp) = 652 | base * (power base exp) 653 | powerSuccPowerLeft base exp = Refl 654 | 655 | total multPowerPowerPlus : (base : Nat) -> (exp : Nat) -> (exp' : Nat) -> 656 | (power base exp) * (power base exp') = power base (exp + exp') 657 | multPowerPowerPlus base Z exp' = 658 | rewrite sym (plusZeroRightNeutral (power base exp')) in Refl 659 | multPowerPowerPlus base (S exp) exp' = 660 | let inductiveHypothesis = multPowerPowerPlus base exp exp' in 661 | rewrite sym inductiveHypothesis in 662 | rewrite sym (multAssociative base (power base exp) (power base exp')) in 663 | Refl 664 | 665 | total powerZeroOne : (base : Nat) -> power base 0 = S Z 666 | powerZeroOne base = Refl 667 | 668 | total powerOneNeutral : (base : Nat) -> power base 1 = base 669 | powerOneNeutral Z = Refl 670 | powerOneNeutral (S base) = 671 | let inductiveHypothesis = powerOneNeutral base in 672 | rewrite inductiveHypothesis in Refl 673 | 674 | total powerOneSuccOne : (exp : Nat) -> power 1 exp = S Z 675 | powerOneSuccOne Z = Refl 676 | powerOneSuccOne (S exp) = 677 | let inductiveHypothesis = powerOneSuccOne exp in 678 | rewrite inductiveHypothesis in Refl 679 | 680 | total powerSuccSuccMult : (base : Nat) -> power base 2 = mult base base 681 | powerSuccSuccMult Z = Refl 682 | powerSuccSuccMult (S base) = rewrite multOneRightNeutral base in Refl 683 | 684 | total powerPowerMultPower : (base : Nat) -> (exp : Nat) -> (exp' : Nat) -> 685 | power (power base exp) exp' = power base (exp * exp') 686 | powerPowerMultPower base exp Z = rewrite multZeroRightZero exp in Refl 687 | powerPowerMultPower base exp (S exp') = 688 | let inductiveHypothesis = powerPowerMultPower base exp exp' in 689 | rewrite inductiveHypothesis in 690 | rewrite multRightSuccPlus exp exp' in 691 | rewrite sym (multPowerPowerPlus base exp (mult exp exp')) in 692 | Refl 693 | 694 | -- Pred 695 | total predSucc : (n : Nat) -> pred (S n) = n 696 | predSucc n = Refl 697 | 698 | total minusSuccPred : (left : Nat) -> (right : Nat) -> 699 | minus left (S right) = pred (minus left right) 700 | minusSuccPred Z right = Refl 701 | minusSuccPred (S left) Z = 702 | rewrite minusZeroRight left in Refl 703 | minusSuccPred (S left) (S right) = 704 | let inductiveHypothesis = minusSuccPred left right in 705 | rewrite inductiveHypothesis in Refl 706 | 707 | -- ifThenElse 708 | total ifThenElseSuccSucc : (cond : Bool) -> (t : Nat) -> (f : Nat) -> 709 | S (ifThenElse cond t f) = ifThenElse cond (S t) (S f) 710 | ifThenElseSuccSucc True t f = Refl 711 | ifThenElseSuccSucc False t f = Refl 712 | 713 | total ifThenElsePlusPlusLeft : (cond : Bool) -> (left : Nat) -> (t : Nat) -> (f : Nat) -> 714 | left + (ifThenElse cond t f) = ifThenElse cond (left + t) (left + f) 715 | ifThenElsePlusPlusLeft True left t f = Refl 716 | ifThenElsePlusPlusLeft False left t f = Refl 717 | 718 | total ifThenElsePlusPlusRight : (cond : Bool) -> (right : Nat) -> (t : Nat) -> (f : Nat) -> 719 | (ifThenElse cond t f) + right = ifThenElse cond (t + right) (f + right) 720 | ifThenElsePlusPlusRight True right t f = Refl 721 | ifThenElsePlusPlusRight False right t f = Refl 722 | 723 | total ifThenElseMultMultLeft : (cond : Bool) -> (left : Nat) -> (t : Nat) -> (f : Nat) -> 724 | left * (ifThenElse cond t f) = ifThenElse cond (left * t) (left * f) 725 | ifThenElseMultMultLeft True left t f = Refl 726 | ifThenElseMultMultLeft False left t f = Refl 727 | 728 | total ifThenElseMultMultRight : (cond : Bool) -> (right : Nat) -> (t : Nat) -> (f : Nat) -> 729 | (ifThenElse cond t f) * right = ifThenElse cond (t * right) (f * right) 730 | ifThenElseMultMultRight True right t f = Refl 731 | ifThenElseMultMultRight False right t f = Refl 732 | 733 | -- Orders 734 | total lteNTrue : (n : Nat) -> lte n n = True 735 | lteNTrue Z = Refl 736 | lteNTrue (S n) = lteNTrue n 737 | 738 | total LTESuccZeroFalse : (n : Nat) -> lte (S n) Z = False 739 | LTESuccZeroFalse Z = Refl 740 | LTESuccZeroFalse (S n) = Refl 741 | 742 | -- Minimum and maximum 743 | total maximumAssociative : (l,c,r : Nat) -> maximum l (maximum c r) = maximum (maximum l c) r 744 | maximumAssociative Z c r = Refl 745 | maximumAssociative (S k) Z r = Refl 746 | maximumAssociative (S k) (S j) Z = Refl 747 | maximumAssociative (S k) (S j) (S i) = rewrite maximumAssociative k j i in Refl 748 | 749 | total maximumCommutative : (l, r : Nat) -> maximum l r = maximum r l 750 | maximumCommutative Z Z = Refl 751 | maximumCommutative Z (S k) = Refl 752 | maximumCommutative (S k) Z = Refl 753 | maximumCommutative (S k) (S j) = rewrite maximumCommutative k j in Refl 754 | 755 | total maximumIdempotent : (n : Nat) -> maximum n n = n 756 | maximumIdempotent Z = Refl 757 | maximumIdempotent (S k) = cong (maximumIdempotent k) 758 | 759 | total minimumAssociative : (l,c,r : Nat) -> minimum l (minimum c r) = minimum (minimum l c) r 760 | minimumAssociative Z c r = Refl 761 | minimumAssociative (S k) Z r = Refl 762 | minimumAssociative (S k) (S j) Z = Refl 763 | minimumAssociative (S k) (S j) (S i) = rewrite minimumAssociative k j i in Refl 764 | 765 | total minimumCommutative : (l, r : Nat) -> minimum l r = minimum r l 766 | minimumCommutative Z Z = Refl 767 | minimumCommutative Z (S k) = Refl 768 | minimumCommutative (S k) Z = Refl 769 | minimumCommutative (S k) (S j) = rewrite minimumCommutative k j in Refl 770 | 771 | total minimumIdempotent : (n : Nat) -> minimum n n = n 772 | minimumIdempotent Z = Refl 773 | minimumIdempotent (S k) = cong (minimumIdempotent k) 774 | 775 | total minimumZeroZeroRight : (right : Nat) -> minimum 0 right = Z 776 | minimumZeroZeroRight Z = Refl 777 | minimumZeroZeroRight (S right) = minimumZeroZeroRight right 778 | 779 | total minimumZeroZeroLeft : (left : Nat) -> minimum left 0 = Z 780 | minimumZeroZeroLeft Z = Refl 781 | minimumZeroZeroLeft (S left) = Refl 782 | 783 | total minimumSuccSucc : (left : Nat) -> (right : Nat) -> 784 | minimum (S left) (S right) = S (minimum left right) 785 | minimumSuccSucc Z Z = Refl 786 | minimumSuccSucc (S left) Z = Refl 787 | minimumSuccSucc Z (S right) = Refl 788 | minimumSuccSucc (S left) (S right) = Refl 789 | 790 | total maximumZeroNRight : (right : Nat) -> maximum Z right = right 791 | maximumZeroNRight Z = Refl 792 | maximumZeroNRight (S right) = Refl 793 | 794 | total maximumZeroNLeft : (left : Nat) -> maximum left Z = left 795 | maximumZeroNLeft Z = Refl 796 | maximumZeroNLeft (S left) = Refl 797 | 798 | total maximumSuccSucc : (left : Nat) -> (right : Nat) -> 799 | S (maximum left right) = maximum (S left) (S right) 800 | maximumSuccSucc Z Z = Refl 801 | maximumSuccSucc (S left) Z = Refl 802 | maximumSuccSucc Z (S right) = Refl 803 | maximumSuccSucc (S left) (S right) = Refl 804 | 805 | total sucMaxL : (l : Nat) -> maximum (S l) l = (S l) 806 | sucMaxL Z = Refl 807 | sucMaxL (S l) = cong (sucMaxL l) 808 | 809 | total sucMaxR : (l : Nat) -> maximum l (S l) = (S l) 810 | sucMaxR Z = Refl 811 | sucMaxR (S l) = cong (sucMaxR l) 812 | 813 | total sucMinL : (l : Nat) -> minimum (S l) l = l 814 | sucMinL Z = Refl 815 | sucMinL (S l) = cong (sucMinL l) 816 | 817 | total sucMinR : (l : Nat) -> minimum l (S l) = l 818 | sucMinR Z = Refl 819 | sucMinR (S l) = cong (sucMinR l) 820 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Awesome Idris [![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/sindresorhus/awesome) 5 | 6 | [](https://www.idris-lang.org/) 7 | 8 | > An auxiliary list of awesome [Idris](https://www.idris-lang.org/) resources. 9 | 10 | Idris is a general purpose pure functional programming language with dependent types. Dependent types allow types to be predicated on values, meaning that some aspects of a program’s behaviour can be specified precisely in the type. It is compiled, with eager evaluation. Its features are influenced by Haskell and ML. 11 | 12 | ## Contents 13 | 14 | - [Official resources](#official-resources) 15 | - [Articles](#articles) 16 | - [Books](#books) 17 | - [Papers](#papers) 18 | - [Presentations](#presentations) 19 | - [Projects](#projects) 20 | 21 | ### Official resources 22 | 23 | * [Official website](https://www.idris-lang.org/) 24 | * [Official repo](https://github.com/idris-lang/Idris-dev) 25 | 26 | ### Articles 27 | 28 | * [10 things Idris improved over Haskell](https://deque.blog/2017/06/14/10-things-idris-improved-over-haskell/) 29 | * [Meet Idris, a language that will change the way you think about programming](https://crufter.com/idris-a-language-that-will-change-the-way-you-think-about-programming) 30 | * [Tests vs. Types](http://kevinmahoney.co.uk/articles/tests-vs-types/) 31 | 32 | ### Books 33 | 34 | * [Type Driven Development With Idris](https://www.manning.com/books/type-driven-development-with-idris) - Most important book published so far. 35 | * [Type Theory and Functional Programming](https://www.cs.kent.ac.uk/people/staff/sjt/TTFP/) 36 | * [Programming in Martin-Löf's Type Theory](http://www.cse.chalmers.se/research/group/logic/book/book.pdf) 37 | * [Software Foundations](https://idris-hackers.github.io/software-foundations/pdf/sf-idris-2018.pdf) - Repo is [here](https://github.com/idris-hackers/software-foundations). 38 | * [Gentle Introduction to Dependent Types with Idris](https://leanpub.com/gidti) 39 | 40 | ### Papers 41 | 42 | * [Elaborator Reflection: Extending Idris in Idris](https://eb.host.cs.st-andrews.ac.uk/drafts/elab-reflection.pdf) - David Christiansen and Edwin Brady, 2016. 43 | * [Cross-platform Compilers for Functional Languages](https://eb.host.cs.st-andrews.ac.uk/drafts/compile-idris.pdf) - Edwin Brady, 2015. 44 | * [Programming and Reasoning with Side-Effects in Idris](https://eb.host.cs.st-andrews.ac.uk/drafts/eff-tutorial.pdf) - Edwin Brady, 2014. 45 | * [Idris, a General Purpose Dependently Typed Programming Language: Design and Implementation](https://pdfs.semanticscholar.org/1407/220ca09070233dca256433430d29e5321dc2.pdf) - Edwin Brady, 2013. 46 | * [Programming and Reasoning with Algebraic Effects and Dependent Types](https://eb.host.cs.st-andrews.ac.uk/drafts/effects.pdf) - Edwin Brady, 2013. 47 | * [Sequential decision problems, dependently typed solutions](http://eb.host.cs.st-andrews.ac.uk/writings/plmms13.pdf) - Nicola Botta, Cezar Ionescu and Edwin Brady, 2013. 48 | * [Programming in Idris: a tutorial](http://eb.host.cs.st-andrews.ac.uk/writings/idris-tutorial.pdf) - Edwin Brady, 2012. 49 | * [Idris — Systems Programming Meets Full Dependent Types](https://eb.host.cs.st-andrews.ac.uk/writings/plpv11.pdf) - Edwin Brady, 2011. 50 | * [Scrapping your Inefficient Engine: using Partial Evaluation to Improve Domain-Specific Language Implementation](http://eb.host.cs.st-andrews.ac.uk/writings/icfp10.pdf) - Edwin Brady and Kevin Hammond, 2010. 51 | * [Correct-by-Construction Concurrency: using Dependent Types to Verify Implementations of Effectful Resource Usage Protocols](http://eb.host.cs.st-andrews.ac.uk/writings/fi-cbc.pdf) - Edwin Brady and Kevin Hammond, 2010. 52 | * [Domain Specific Languages (DSLs) for Network Protocols](http://eb.host.cs.st-andrews.ac.uk/drafts/ngna2009-dsl.pdf) - Saleem Bhatti, Edwin Brady, Kevin Hammond and James McKinna, 2009. 53 | * [Lightweight Invariants with Full Dependent Types](http://eb.host.cs.st-andrews.ac.uk/drafts/tfp08.pdf) - Edwin Brady, Christoph Herrmann and Kevin Hammond, 2008. 54 | 55 | ### Presentations 56 | 57 | * [Idris: General Purpose Programming with Dependent Types](https://www.youtube.com/watch?v=vkIlW797JN8) - Presentation by Edwin Brady, Idris' creator. 58 | 59 | ### Projects 60 | 61 | * [GitHub's trending Idris repos](https://github.com/trending/idris) 62 | * [iridium](https://github.com/puffnfresh/iridium) - xmonad with the X11 abstracted and configured with Idris. 63 | * [lightyear](https://github.com/ziman/lightyear) - Parser combinators for Idris. 64 | * [quantities](https://github.com/timjb/quantities) Type-safe physical computations and unit conversions in Idris. 65 | * [idris-type-providers](https://github.com/david-christiansen/idris-type-providers) - Type provider library for Idris. 66 | * [IdrisScript](https://github.com/idris-hackers/IdrisScript) - FFI Bindings to interact with the unsafe world of JavaScript. 67 | * [idris-containers](https://github.com/jfdm/idris-containers) - Various data structures for use in the Idris Language. 68 | * [IdrisSqlite](https://github.com/david-christiansen/IdrisSqlite) - Effectful bindings for SQLite. 69 | * [idris-http](https://github.com/uwap/idris-http) - HTTP library for Idris. 70 | * [RingIdris](https://github.com/FranckS/RingIdris) - Ring solver for Idris. 71 | * [specdris](https://github.com/pheymann/specdris) - Test framework for Idris. 72 | * [idris-config](https://github.com/jfdm/idris-config) - Parsers for various configuration files written in Idris. 73 | * [probability](https://github.com/BlackBrane/probability) - Probabilistic computation in Idris. 74 | * [idris-protobuf](https://github.com/google/idris-protobuf) - Partial implementation of Protocol Buffers in Idris. 75 | * [idris-free](https://github.com/idris-hackers/idris-free) - Free Monads and useful constructions to work with them. 76 | * [idris-ct](https://github.com/statebox/idris-ct) - Formally verified category theory library 77 | * [typedefs](https://github.com/typedefs/typedefs) - Programming language-agnostic, algebraic data type definition language 78 | 79 | ### Backends 80 | 81 | * [idris-jvm](https://github.com/mmhelloworld/idris-jvm) - JVM bytecode backend for Idris. 82 | * [idris-llvm](https://github.com/idris-hackers/idris-llvm) - LLVM backend. 83 | * [idris-erlang](https://github.com/lenary/idris-erlang) - Erlang backend. 84 | * [idris-malfunction](https://github.com/stedolan/idris-malfunction) - Experimental Malfunction (OCaml internal representation) backend. 85 | 86 | ### Build tools | Package managers 87 | 88 | - [Idris Rules](http://idris.build) - Idris rules for Bazel 89 | - [Ikan](https://github.com/idris-industry/ikan) - A package manager for idris, in idris 90 | - [Elba](https://github.com/elba/elba) - A package manager for Idris 91 | - [idream](https://github.com/idream-build/idream) - A simple build system for Idris 92 | 93 | ### Community 94 | 95 | * [Mailing list](http://groups.google.com/group/idris-lang) 96 | * IRC: #idris on [freenode.net](https://webchat.freenode.net/) 97 | * [GitHub organization](https://github.com/idris-hackers) 98 | * [Community Standards](https://www.idris-lang.org/documentation/community-standards/) 99 | 100 | ## License 101 | 102 | [![CC0](http://mirrors.creativecommons.org/presskit/buttons/88x31/svg/cc-zero.svg)](https://creativecommons.org/publicdomain/zero/1.0/) 103 | -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidelines 2 | 3 | # The pull request should have a useful title. 4 | 5 | ## Table of Contents 6 | 7 | - [Adding to this list](#adding-to-this-list) 8 | - [Creating your own awesome list](#creating-your-own-awesome-list) 9 | - [Adding something to an awesome list](#adding-something-to-an-awesome-list) 10 | - [Updating your Pull Request](#updating-your-pull-request) 11 | 12 | ## Adding to this list 13 | 14 | Please ensure your pull request adheres to the following guidelines: 15 | 16 | - Search previous suggestions before making a new one, as yours may be a duplicate. 17 | - Make sure the list is useful before submitting. That implies it has enough content and every item has a good succinct description. 18 | - Make an individual pull request for each suggestion. 19 | - Use [title-casing](http://titlecapitalization.com) (AP style). 20 | - Use the following format: `[List Name](link)` 21 | - Link additions should be added to the bottom of the relevant category. 22 | - New categories or improvements to the existing categorization are welcome. 23 | - Check your spelling and grammar. 24 | - Make sure your text editor is set to remove trailing whitespace. 25 | - The pull request and commit should have a useful title. 26 | - The body of your commit message should contain a link to the repository. 27 | 28 | Thank you for your suggestions! 29 | 30 | ## Creating your own awesome list 31 | 32 | To create your own list, check out the [instructions](create-list.md). 33 | 34 | ## Adding something to an awesome list 35 | 36 | If you have something awesome to contribute to an awesome list, this is how you do it. 37 | 38 | You'll need a [GitHub account](https://github.com/join)! 39 | 40 | 1. Access the awesome list's GitHub page. For example: https://github.com/sindresorhus/awesome 41 | 2. Click on the `readme.md` file: ![Step 2 Click on Readme.md](https://cloud.githubusercontent.com/assets/170270/9402920/53a7e3ea-480c-11e5-9d81-aecf64be55eb.png) 42 | 3. Now click on the edit icon. ![Step 3 - Click on Edit](https://cloud.githubusercontent.com/assets/170270/9402927/6506af22-480c-11e5-8c18-7ea823530099.png) 43 | 4. You can start editing the text of the file in the in-browser editor. Make sure you follow guidelines above. You can use [GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown/). ![Step 4 - Edit the file](https://cloud.githubusercontent.com/assets/170270/9402932/7301c3a0-480c-11e5-81f5-7e343b71674f.png) 44 | 5. Say why you're proposing the changes, and then click on "Propose file change". ![Step 5 - Propose Changes](https://cloud.githubusercontent.com/assets/170270/9402937/7dd0652a-480c-11e5-9138-bd14244593d5.png) 45 | 6. Submit the [pull request](https://help.github.com/articles/using-pull-requests/)! 46 | 47 | ## Updating your Pull Request 48 | 49 | Sometimes, a maintainer of an awesome list will ask you to edit your Pull Request before it is included. This is normally due to spelling errors or because your PR didn't match the awesome-* list guidelines. 50 | 51 | [Here](https://github.com/RichardLitt/docs/blob/master/amending-a-commit-guide.md) is a write up on how to change a Pull Request, and the different ways you can do that. 52 | --------------------------------------------------------------------------------