fc210e5cdd97d60ce7290b4ac4227adc51119e2786bcacb671b7ad9cb6cda427.tri (22046B)
1 !export * 2 -- 1. t t a b -> a 3 -- 2. t (t a) b c -> a c (b c) 4 -- 3a. t (t a b) c t -> a 5 -- 3b. t (t a b) c (t u) -> b u 6 -- 3c. t (t a b) c (t u v) -> c u v 7 8 false = t 9 _ = t 10 true = t t 11 id a = a 12 const a b = a 13 pair = t 14 if cond then else = t (t else (t t then)) t cond 15 16 y = ((mut wait fun : wait mut (x : fun (wait mut x))) 17 (x : x x) 18 (a0 a1 a2 : t (t a0) (t t a2) a1)) 19 20 compose f g x = f (g x) 21 22 triage leaf stem fork = t (t leaf stem) fork 23 test = triage "Leaf" (_ : "Stem") (_ _ : "Fork") 24 25 matchBool = (onTrue onFalse : triage 26 onFalse 27 (_ : onTrue) 28 (_ _ : onTrue) 29 ) 30 31 lAnd = (triage 32 (_ : false) 33 (_ x : x) 34 (_ _ x : x)) 35 36 lOr = (triage 37 (x : x) 38 (_ _ : true) 39 (_ _ _ : true)) 40 41 matchPair a = triage _ _ a 42 43 fst p = matchPair takeFirst p 44 where takeFirst a b = a 45 snd p = matchPair takeSecond p 46 where takeSecond a b = b 47 48 resultIsOk result = 49 matchResult (errR rest : false) (val rest : true) result 50 51 resultIsErr result = 52 matchResult (errR rest : true) (val rest : false) result 53 54 not? = matchBool false true 55 and? = matchBool id (_ : false) 56 57 or? = (x z : 58 matchBool 59 (matchBool true true z) 60 (matchBool true false z) 61 x) 62 63 xor? = (x z : 64 matchBool 65 (matchBool false true z) 66 (matchBool true false z) 67 x) 68 69 equal? = y (self : triage 70 (triage 71 true 72 (_ : false) 73 (_ _ : false)) 74 (ax : 75 triage 76 false 77 (self ax) 78 (_ _ : false)) 79 (ax ay : 80 triage 81 false 82 (_ : false) 83 (bx by : lAnd (self ax bx) (self ay by)))) 84 85 succ = y (self : 86 triage 87 1 88 t 89 (triage 90 (t (t t)) 91 (_ tail : t t (self tail)) 92 t)) 93 94 ok value rest = pair true (pair value rest) 95 err msg rest = pair false (pair msg rest) 96 97 matchResult errCase okCase result = 98 matchPair 99 (tag payload : 100 matchPair 101 (value rest : 102 matchBool 103 (okCase value rest) 104 (errCase value rest) 105 tag) 106 payload) 107 result 108 109 -- --------------------------------------------------------------------------- 110 -- Maybe / Option type 111 -- --------------------------------------------------------------------------- 112 113 nothing = t 114 just x = t x 115 116 matchMaybe nothingCase justCase maybe = 117 triage 118 nothingCase 119 justCase 120 (_ _ : nothingCase) 121 maybe 122 123 maybe default f m = matchMaybe default f m 124 maybeMap f m = matchMaybe nothing (x : just (f x)) m 125 maybeBind m f = matchMaybe nothing f m 126 maybeOr default m = matchMaybe default id m 127 maybe? = matchMaybe false (_ : true) 128 129 -- --------------------------------------------------------------------------- 130 -- Lazy eliminators 131 -- 132 -- A strict eliminator evaluates both branches because they are ordinary 133 -- arguments. Give a branch that recurses, looks something up, or builds 134 -- structure to one of these instead: it becomes a thunk and only the selected 135 -- branch is ever applied. 136 -- --------------------------------------------------------------------------- 137 138 lazyBool = (thenK elseK cond : 139 ((chosen : chosen t) 140 (matchBool 141 thenK 142 elseK 143 cond))) 144 145 -- `triage` selects a thunk directly: a cons is a Fork, so the cons case sits 146 -- in the fork slot, exactly as in `matchList` below. 147 lazyList = (nilK consK xs : 148 ((chosen : chosen t) 149 (triage 150 nilK 151 _ 152 (h r : (_ : consK h r)) 153 xs))) 154 155 lazyMaybe = (noneK someK m : 156 ((chosen : chosen t) 157 (matchMaybe 158 noneK 159 (x : (_ : someK x)) 160 m))) 161 162 lazyResult = (errK okK result : 163 ((chosen : chosen t) 164 (matchResult 165 (code rest : (_ : errK code rest)) 166 (value rest : (_ : okK value rest)) 167 result))) 168 169 -- --------------------------------------------------------------------------- 170 -- Basic arithmetic 171 -- --------------------------------------------------------------------------- 172 173 ifLazy = (cond thenK elseK : 174 matchBool 175 (thenK t) 176 (elseK t) 177 cond) 178 179 andLazy? = (a bK : 180 ifLazy 181 a 182 bK 183 (_ : false)) 184 185 pred_ = y (self : triage 186 0 187 0 188 (bit rest : 189 ifLazy 190 bit 191 (_ : matchBool 192 (t t rest) 193 0 194 rest) 195 (_ : t (t t) (self rest)))) 196 197 pred @nat? =@nat? pred_ 198 199 isZero_? = triage true (_ : false) (_ _ : false) 200 201 isZero? @nat? =@bool? isZero_? 202 203 add @nat? @nat? =@nat? (y (self x y : 204 triage 205 y 206 (_ : succ y) 207 (_ _ : succ (self (pred_ x) y)) 208 x)) 209 210 sub @nat? @nat? =@nat? y (self a b : 211 ifLazy 212 (isZero_? b) 213 (_ : a) 214 (_ : self (pred_ a) (pred_ b))) 215 216 lte_? = y (self a b : 217 ifLazy 218 (isZero_? a) 219 (_ : true) 220 (_ : 221 ifLazy 222 (isZero_? b) 223 (_ : false) 224 (_ : self (pred_ a) (pred_ b)))) 225 226 lte? @nat? @nat? =@bool? lte_? 227 228 gte_? = a b : lte_? b a 229 230 gte? @nat? @nat? =@bool? gte_? 231 232 lt_? = a b : and? (lte_? a b) (not? (equal? a b)) 233 234 lt? @nat? @nat? =@bool? lt_? 235 236 gt_? = a b : lt_? b a 237 238 gt? @nat? @nat? =@bool? gt_? 239 240 mul @nat? @nat? =@nat? y (self a b : 241 ifLazy 242 (isZero_? b) 243 (_ : 0) 244 (_ : add a (self a (pred_ b)))) 245 246 div @nat? @nat? =@nat? y (self a b : 247 ifLazy 248 (isZero_? b) 249 (_ : 0) 250 (_ : ifLazy 251 (lt_? a b) 252 (_ : 0) 253 (_ : succ (self (sub a b) b)))) 254 255 mod @nat? @nat? =@nat? y (self a b : 256 ifLazy 257 (isZero_? b) 258 (_ : 0) 259 (_ : ifLazy 260 (lt_? a b) 261 (_ : a) 262 (_ : self (sub a b) b))) 263 264 pow @nat? @nat? =@nat? y (self a b : 265 ifLazy 266 (isZero_? b) 267 (_ : 1) 268 (_ : mul a (self a (pred_ b)))) 269 270 even? n = (triage 271 true 272 (_ : false) 273 (bit _ : isZero_? bit) 274 n) 275 276 odd? = (n : not? (even? n)) 277 278 min @nat? @nat? =@nat? (a b : ifLazy (lte_? a b) (_ : a) (_ : b)) 279 280 max @nat? @nat? =@nat? (a b : ifLazy (lte_? a b) (_ : b) (_ : a)) 281 282 -- --------------------------------------------------------------------------- 283 -- Result combinators 284 -- --------------------------------------------------------------------------- 285 286 mapResult = (f result : 287 matchResult 288 (code rest : err code rest) 289 (value rest : ok (f value) rest) 290 result) 291 292 bindResult = (result f : 293 matchResult 294 (code rest : err code rest) 295 (value rest : f value rest) 296 result) 297 298 resultOr = (default result : 299 matchResult 300 (_ _ : default) 301 (value _ : value) 302 result) 303 304 resultMapErr = (f result : 305 matchResult 306 (code rest : err (f code) rest) 307 (value rest : ok value rest) 308 result) 309 310 -- --------------------------------------------------------------------------- 311 -- List 312 -- --------------------------------------------------------------------------- 313 314 matchList = a b : triage a _ b 315 316 emptyList? = matchList true (_ _ : false) 317 head xs@(nonEmptyListOf anyC) =@anyC matchList t (h _ : h) xs 318 tail xs@(nonEmptyListOf anyC) =@(listOf anyC) matchList t (_ r : r) xs 319 320 append_ self xs ys = 321 matchList 322 ys 323 (h r : pair h (self r ys)) 324 xs 325 append = xs ys : y append_ xs ys 326 327 lExist?_ self x xs = 328 matchList 329 false 330 (h r : or? (equal? x h) (self x r)) 331 xs 332 lExist? = x xs : y lExist?_ x xs 333 334 map_ self l f = 335 matchList 336 t 337 (h r : pair (f h) (self r f)) 338 l 339 map = f l : y map_ l f 340 341 filter_ self l f = 342 matchList 343 t 344 (h r : 345 matchBool 346 (pair h (self r f)) 347 (self r f) 348 (f h)) 349 l 350 filter = f l : y filter_ l f 351 352 foldl_ self l f acc = 353 matchList 354 acc 355 (h r : self r f (f acc h)) 356 l 357 foldl = f x l : y foldl_ l f x 358 359 foldr_ self l f x = 360 matchList 361 x 362 (h r : f (self r f x) h) 363 l 364 foldr = f x l : y foldr_ l f x 365 366 length_ self xs = 367 matchList 368 0 369 (_ r : succ (self r)) 370 xs 371 length @(listOf anyC) =@nat? y length_ 372 373 reverse_ self xs acc = 374 matchList 375 acc 376 (h r : self r (pair h acc)) 377 xs 378 reverse = xs : y reverse_ xs t 379 380 snoc_ self x xs = 381 matchList 382 (pair x t) 383 (h r : pair h (self x r)) 384 xs 385 snoc = x xs : y snoc_ x xs 386 387 count_ self x xs = 388 matchList 389 0 390 (h r : 391 matchBool 392 (succ (self x r)) 393 (self x r) 394 (equal? x h)) 395 xs 396 count = x xs : y count_ x xs 397 398 last_ self xs = 399 matchList 400 t 401 (h r : 402 matchBool 403 h 404 (self r) 405 (emptyList? r)) 406 xs 407 last @(nonEmptyListOf anyC) =@anyC y last_ 408 409 all?_ self pred xs = 410 matchList 411 true 412 (h r : and? (pred h) (self pred r)) 413 xs 414 all? = pred xs : y all?_ pred xs 415 416 any?_ self pred xs = 417 matchList 418 false 419 (h r : or? (pred h) (self pred r)) 420 xs 421 any? = pred xs : y any?_ pred xs 422 423 intersect = xs ys : filter (x : lExist? x ys) xs 424 425 nth_ self xs n i = 426 matchList 427 t 428 (h r : 429 matchBool 430 h 431 (self r n (succ i)) 432 (equal? i n)) 433 xs 434 nth = n xs : y nth_ xs n 0 435 436 headMaybe = matchList nothing (h _ : just h) 437 438 lastMaybe_ self xs = 439 matchList 440 nothing 441 (h r : 442 matchBool 443 (just h) 444 (self r) 445 (emptyList? r)) 446 xs 447 lastMaybe = xs : y lastMaybe_ xs 448 449 nthMaybe_ self xs n i = 450 matchList 451 nothing 452 (h r : 453 matchBool 454 (just h) 455 (self r n (succ i)) 456 (equal? i n)) 457 xs 458 nthMaybe = n xs : y nthMaybe_ xs n 0 459 460 take_ self xs n i = 461 matchList 462 t 463 (h r : 464 matchBool 465 t 466 (pair h (self r n (succ i))) 467 (equal? i n)) 468 xs 469 take = n xs : y take_ xs n 0 470 471 drop_ self xs n i = 472 matchBool 473 xs 474 (matchList 475 t 476 (_ r : self r n (succ i)) 477 xs) 478 (equal? i n) 479 drop = n xs : y drop_ xs n 0 480 481 splitAt = n xs : pair (take n xs) (drop n xs) 482 483 concatMap_ self f xs = 484 matchList 485 t 486 (h r : append (f h) (self f r)) 487 xs 488 concatMap = f xs : y concatMap_ f xs 489 490 find_ self pred xs = 491 matchList 492 nothing 493 (h r : 494 matchBool 495 (just h) 496 (self pred r) 497 (pred h)) 498 xs 499 find = pred xs : y find_ pred xs 500 501 partition_ self pred xs trues falses = 502 matchList 503 (pair (reverse trues) (reverse falses)) 504 (h r : 505 matchBool 506 (self pred r (pair h trues) falses) 507 (self pred r trues (pair h falses)) 508 (pred h)) 509 xs 510 partition = pred xs : y partition_ pred xs t t 511 512 strLength = length 513 strAppend = append 514 strEq? = equal? 515 strEmpty? = emptyList? 516 517 startsWith?_ self prefix input = 518 matchList 519 true 520 (ph pr : 521 matchList 522 false 523 (sh sr : 524 matchBool 525 (self pr sr) 526 false 527 (equal? ph sh)) 528 input) 529 prefix 530 startsWith? = prefix input : y startsWith?_ prefix input 531 532 endsWith? = prefix str : startsWith? (reverse prefix) (reverse str) 533 534 contains?_ self needle haystack = 535 matchBool 536 true 537 (matchList 538 false 539 (_ r : self needle r) 540 haystack) 541 (startsWith? needle haystack) 542 contains? = needle haystack : y contains?_ needle haystack 543 544 sum @(listOf nat?) =@nat? foldl (acc x : add x acc) 0 545 product @(listOf nat?) =@nat? foldl (acc x : mul x acc) 1 546 547 -- --------------------------------------------------------------------------- 548 -- Generic separators 549 -- 550 -- `lines`, `unlines`, `words` and `unwords` at the bottom of this section are 551 -- the byte-valued special cases of these primitives. 552 -- 553 -- Joining takes any separator; splitting takes one byte. Separators are removed 554 -- rather than kept, and empty fields are preserved. 555 -- --------------------------------------------------------------------------- 556 557 takeWhile_ self xs f = 558 lazyList 559 (_ : t) 560 (h r : 561 lazyBool 562 (_ : pair h (self r f)) 563 (_ : t) 564 (f h)) 565 xs 566 takeWhile = f xs : y takeWhile_ xs f 567 568 dropWhile_ self xs f = 569 lazyList 570 (_ : t) 571 (h r : 572 lazyBool 573 (_ : self r f) 574 (_ : pair h r) 575 (f h)) 576 xs 577 dropWhile = f xs : y dropWhile_ xs f 578 579 -- Byte-level whitespace only: space and horizontal tab (HTTP OWS). 580 spaceByte? = b : equal? b 32 581 tabByte? = b : equal? b 9 582 trimByte? = b : or? (spaceByte? b) (tabByte? b) 583 584 trim = xs : dropWhile trimByte? (reverse (dropWhile trimByte? (reverse xs))) 585 586 intercalate_ self xs sep = 587 lazyList 588 (_ : t) 589 (h r : 590 lazyBool 591 (_ : h) 592 (_ : append h (append sep (self r sep))) 593 (emptyList? r)) 594 xs 595 intercalate = sep xs : y intercalate_ xs sep 596 597 -- Separator after every field, including the last one. Line-oriented formats 598 -- want this: `joinSuffix "\n" xs` terminates the final line while 599 -- `intercalate "\n" xs` does not. 600 joinSuffix_ self xs sep = 601 lazyList 602 (_ : t) 603 (h r : append (append h sep) (self r sep)) 604 xs 605 joinSuffix = sep xs : y joinSuffix_ xs sep 606 607 -- Split on a single byte. 608 -- Empty fields are preserved: `splitOnByte 58 "a::b"` is ["a" "" "b"]. 609 splitByte_ self str byte acc current = 610 lazyList 611 (_ : map reverse (reverse (pair current acc))) 612 (h r : 613 lazyBool 614 (_ : self r byte (pair current acc) t) 615 (_ : self r byte acc (pair h current)) 616 (equal? h byte)) 617 str 618 splitOnByte = byte str : y splitByte_ str byte t t 619 620 -- Every one of these keeps its arguments bound: partially applying a 621 -- multi-argument function at the top level leaves a fixed point exposed. 622 lines = str : splitOnByte 10 str 623 unlines = xs : joinSuffix "\n" xs 624 625 -- Runs of separators collapse: empty fields are dropped. 626 words = str : filter (w : not? (emptyList? w)) (splitOnByte 32 str) 627 unwords = xs : intercalate " " xs 628 629 zipWith_ self f xs ys = 630 matchList 631 t 632 (xh xt : 633 matchList 634 t 635 (yh yt : pair (f xh yh) (self f xt yt)) 636 ys) 637 xs 638 zipWith = f xs ys : y zipWith_ f xs ys 639 640 -- --------------------------------------------------------------------------- 641 -- Core contract type 642 -- 643 -- A contract is an ordinary tricu function: Tree -> Tree -> Result Tree Tree. 644 -- The second argument is the conventional "rest" slot. On success a contract 645 -- returns the checked value wrapped in the standard ok shape; on failure it 646 -- returns a diagnostic wrapped in the standard err shape. 647 -- 648 -- The contract kernel is a globally configurable function selected by the 649 -- runner. It decides whether to accept the contract result, replace it, log 650 -- it, or transform the diagnostic. The default kernel is the identity on the 651 -- contract Result. 652 -- 653 -- The runner may rebind 'kernel' to a different kernel before evaluating 654 -- user code (e.g. via --contract-kernel). 655 -- --------------------------------------------------------------------------- 656 657 contractOk = (value : (rest : ok value rest)) 658 contractErr = (msg : (rest : err msg rest)) 659 660 -- Default contract kernel. Return the contract Result unchanged. 661 defaultKernel = (contract value result : 662 matchResult 663 (msg rest : err msg rest) 664 (v rest : ok v rest) 665 result) 666 667 -- The active kernel. The runner may rebind this name to a different kernel 668 -- before evaluating user code (e.g. via --contract-kernel). Internally, 669 -- withContract dispatches through this binding, so rebinding 'kernel' changes 670 -- the behaviour of every contract boundary in the program. 671 kernel = defaultKernel 672 673 -- Skip-everything kernel. Resume with the original value on failure. 674 skipKernel = (contract value result : 675 matchResult 676 (msg rest : ok value rest) 677 (v rest : ok v rest) 678 result) 679 680 -- Apply a contract and pass the raw Result to the kernel. 681 withContract = (contract value : 682 kernel contract value (contract value t)) 683 684 -- Apply a contract and return the checked value or the diagnostic message. 685 check contract value = 686 matchResult 687 (msg _ : msg) 688 (v _ : v) 689 (withContract contract value) 690 691 -- Apply a contract and return the raw Result (kernel is bypassed). 692 checkContract = (contract value : contract value t) 693 694 -- --------------------------------------------------------------------------- 695 -- Basic contracts 696 -- --------------------------------------------------------------------------- 697 698 -- Any value passes. 699 anyC = (value : contractOk value) 700 701 -- Always fails with the supplied message. 702 neverC = (msg : (value : contractErr msg)) 703 704 -- Build a contract from a predicate that inspects only the value. 705 guardC = (msg predicate value rest : 706 lazyBool 707 (_ : contractOk value rest) 708 (_ : contractErr msg rest) 709 (predicate value)) 710 711 -- Structural natural-number predicate. 712 -- A natural is either Leaf (0) or Fork bit rest where bit is Leaf (even) 713 -- or Stem Leaf (odd) and rest is itself a natural. 714 isNat? = y (self n : 715 triage 716 true 717 (_ : false) 718 (bit r : 719 triage 720 (self r) 721 (_ : self r) 722 (_ _ : false) 723 bit) 724 n) 725 726 -- Natural number contract. 727 nat? = guardC "not a natural number" isNat? 728 729 -- Non-zero natural number contract. 730 nonZero? = guardC "non-zero" (n : and? (isNat? n) (not? (isZero_? n))) 731 732 -- Boolean contract. 733 bool? = guardC "not a boolean" (b : or? (equal? b true) (equal? b false)) 734 735 -- --------------------------------------------------------------------------- 736 -- Contract combinators 737 -- --------------------------------------------------------------------------- 738 739 andC = (c1 c2 value rest : 740 matchResult 741 (msg _ : contractErr msg rest) 742 (v _ : c2 v rest) 743 (c1 value rest)) 744 745 orC = (c1 c2 value rest : 746 matchResult 747 (msg _ : c2 value rest) 748 (v _ : contractOk v rest) 749 (c1 value rest)) 750 751 notC = (c value rest : 752 matchResult 753 (msg _ : contractOk value rest) 754 (_ _ : contractErr "notC: predicate succeeded" rest) 755 (c value rest)) 756 757 mapC = (f c value rest : 758 matchResult 759 (msg _ : contractErr msg rest) 760 (v _ : contractOk (f v) rest) 761 (c value rest)) 762 763 bindC = (c f value rest : 764 matchResult 765 (msg _ : contractErr msg rest) 766 (v _ : f v value rest) 767 (c value rest)) 768 769 -- --------------------------------------------------------------------------- 770 -- Collection contracts 771 -- --------------------------------------------------------------------------- 772 773 listOf = (c value rest : 774 y (self orig xs : 775 matchList 776 (contractOk orig rest) 777 (h r : 778 matchResult 779 (msg _ : contractErr msg rest) 780 (_ _ : self orig r) 781 (c h rest)) 782 xs) value value) 783 784 nonEmptyListOf = (c : 785 andC (guardC "empty list" (xs : not? (emptyList? xs))) (listOf c)) 786 787 pairOf = (c1 c2 p rest : 788 matchPair 789 (a b : 790 matchResult 791 (msg _ : contractErr msg rest) 792 (a' _ : 793 matchResult 794 (msg _ : contractErr msg rest) 795 (b' _ : contractOk (pair a' b') rest) 796 (c2 b rest)) 797 (c1 a rest)) 798 p) 799 800 -- --------------------------------------------------------------------------- 801 -- Higher-order function contracts 802 -- 803 -- These return a Result-wrapped proxy. The proxy itself is a contract: it 804 -- checks arguments on the way in and results on the way out. 805 -- --------------------------------------------------------------------------- 806 807 fnContract = (argC resC f rest : 808 contractOk 809 (x : (rest1 : 810 matchResult 811 (msg _ : contractErr msg rest1) 812 (x' _ : 813 matchResult 814 (msg _ : contractErr msg rest1) 815 (y _ : contractOk y rest1) 816 (withContract resC (f x'))) 817 (withContract argC x))) 818 rest) 819 820 fn2 = (arg1C arg2C resC f rest : 821 contractOk 822 (x : (rest1 : 823 matchResult 824 (msg _ : contractErr msg rest1) 825 (x' _ : 826 contractOk 827 (y : (rest2 : 828 matchResult 829 (msg _ : contractErr msg rest2) 830 (y' _ : 831 matchResult 832 (msg _ : contractErr msg rest2) 833 (z _ : contractOk z rest2) 834 (withContract resC (f x' y'))) 835 (withContract arg2C y))) 836 rest1) 837 (withContract arg1C x))) 838 rest) 839 840 -- --------------------------------------------------------------------------- 841 -- Interaction-tree effect layer 842 -- 843 -- These constructors and combinators layer catchable, composable failures on 844 -- top of the core Result contracts. They reuse the same tags as tricu IO: 845 -- 0 = pureE 846 -- 1 = bindE 847 -- 2 = exceptE 848 -- --------------------------------------------------------------------------- 849 850 pureE = (value : pair 0 value) 851 bindE = (action k : pair 1 (pair action k)) 852 exceptE = (tag value k : pair 2 (pair tag (pair value k))) 853 854 pureM = pureE 855 bindM = bindE 856 857 -- Lift a contract failure into an interaction tree. 858 checkM = (contract value : 859 matchResult 860 (msg _ : exceptE "contract" msg (_ : pureE t)) 861 (checked _ : pureE checked) 862 (contract value t)) 863 864 -- Lift a pure function into the interaction tree. 865 liftM = (f : (x : pureE (f x))) 866 867 -- Interpret a pure interaction tree into a Result. 868 runM = (tree : 869 run tree 870 where run = 871 y (self tree : 872 matchPair 873 (op payload : 874 matchBool 875 -- pureE 876 (contractOk (snd tree) t) 877 (matchBool 878 -- bindE 879 (matchPair 880 (action k : 881 matchResult 882 (msg _ : contractErr msg t) 883 (v _ : self (k v)) 884 (self action)) 885 payload) 886 -- exceptE 887 (matchPair 888 (tag pair : 889 matchPair 890 (value k : 891 contractErr value t) 892 pair) 893 payload) 894 (equal? op 1)) 895 (equal? op 0)) 896 tree)) 897 898 -- Handle matching exceptE nodes by applying the handler to the value and the 899 -- resumption continuation. Non-matching exceptions are left in place. 900 handleM = (tag handler tree : 901 handle tree 902 where handle = 903 y (self tree : 904 matchPair 905 (op payload : 906 matchBool 907 -- pureE 908 tree 909 (matchBool 910 -- bindE 911 (matchPair 912 (action k : 913 bindE (self action) (v : self (k v))) 914 payload) 915 -- exceptE 916 (matchPair 917 (et pair : 918 matchPair 919 (value k : 920 matchBool 921 (self (handler value k)) 922 tree 923 (equal? et tag)) 924 pair) 925 payload) 926 (equal? op 1)) 927 (equal? op 0)) 928 tree)) 929