sire_07_dat.sire (25620B)
1 ; Copyright 2023 The Plunder Authors 2 ; Use of this source code is governed by a BSD-style license that can be 3 ; found in the LICENSE file. 4 5 #### sire_07_dat <- sire_06_rex 6 7 ;;;; Data Structures 8 ;;;; =============== 9 ;;;; 10 ;;;; Rows (vectors), lists, maybe, either, and operations on these 11 ;;;; datatype. 12 13 14 ;;; Imports ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 15 16 :| sire_01_fan 17 :| sire_02_bit [if ifz else ifNot and or not bit TRUE FALSE] 18 :| sire_03_nat [dec sub add lsh rsh div roundUp mod mul] 19 :| sire_03_nat [even odd] 20 :| sire_03_nat [LT GT EQ] 21 :| sire_05_row [head arity len idx get mut] 22 :| sire_04_cmp [eql neq cmp lth gth lte gte min isZero] 23 :| sire_05_row 24 :| sire_06_rex 25 26 27 ;;; Fake Typing Syntax ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 28 29 = ({>} st rex err ok) 30 @ heir (rexHeir rex) 31 | ifz heir 32 | err rex {> annotations require an heir to annotate} 33 | ok st heir 34 35 = ({\} st _ err ok) 36 | ok st '(#*) 37 38 = ({#typedef} st _ err ok) 39 | ok st '(#*) 40 41 42 ;;; Basic Row Operations ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 43 44 (rowIndexed row)=(gen len-row i&(v2 i | idx i row)) 45 46 = (rep i n) | gen n (const i) 47 = (rowAnd v) | foldr and TRUE v 48 = (rowOr v) | foldr or FALSE v 49 = (sum v) | foldr add 0 v 50 = (sumOf f v) | foldr (x acc & add acc (f x)) 0 v 51 = (all f v) | rowAnd (map f v) 52 = (any f v) | rowOr (map f v) 53 = (cat vs) | foldr weld v0 vs 54 = (catMap f r) | cat (map f r) 55 = (zipWith f a b) | gen (min len-a len-b) i&(f idx-i-a idx-i-b) 56 = (zip a b) | zipWith v2 a b 57 = (has ele row) | any (eql ele) row 58 = (slash v s e) | gen (sub e s) i&(get v | add s i) 59 = (slice v s e) | slash v s (min e | len v) 60 = (drop n v) | slice v n (len v) 61 = (take n v) | slice v 0 n 62 = (splitAt i r) | v2 (take i r) (drop i r) 63 64 = (foldr1 f xs) 65 | if (null xs) 66 | die {fold1: empty row} 67 @ las (dec len-xs) 68 | foldr f (idx las xs) (take las xs) 69 70 = (chunks sz row) 71 | gen | div (roundUp len-row sz) sz 72 & ix 73 @ start (mul ix sz) 74 | slice row start (add start sz) 75 76 = (intersperse sep row) 77 | gen | dec | mul 2 | len row 78 & ix 79 | if odd-ix sep 80 | get row (div ix 2) 81 82 (strictRow a)=(foldl const a a) 83 84 (seqRow row b)=(foldr seq b row) 85 86 = (insert ix val row) 87 | gen (inc len-row) 88 & i 89 | switch (cmp i ix) 0 90 | v3 (idx i row) val (idx dec-i row) 91 92 =?= (v2 9 0) | insert 0 9 (v1 0) 93 =?= (v2 0 9) | insert 1 9 (v1 0) 94 =?= (v2 0 0) | insert 2 9 (v1 0) 95 =?= (v3 9 0 1) | insert 0 9 (v2 0 1) 96 =?= (v3 0 9 1) | insert 1 9 (v2 0 1) 97 =?= (v3 0 1 9) | insert 2 9 (v2 0 1) 98 =?= (v3 0 1 0) | insert 3 9 (v2 0 1) 99 100 101 ;;; Generating Basic Sire Expressions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 102 103 = (appE exps) 104 | if (eql 1 (len exps)) 105 | idx 0 exps 106 | NEST {#|} exps 0 107 108 ; Same as `appE` but formatted in open mode. 109 = (bopE exps) 110 | if (eql 1 (len exps)) 111 | idx 0 exps 112 | OPEN {#|} exps 0 113 114 ; Same as `appE` but formatted in open mode with last argument as heir. 115 = (bapE exps) 116 @ siz (len exps) 117 @ las (dec siz) 118 | if (eql 1 siz) (idx 0 exps) 119 | OPEN {#|} (take las exps) (idx las exps) 120 121 = (rowE exps) 122 @ widt (len exps) 123 | appE 124 | rowCons (EMBD (cow widt)) 125 | rev exps 126 127 ; Same as `rowE` but formatted in open mode. 128 = (bowE exps) 129 @ widt (len exps) 130 | bopE 131 | rowCons (EMBD (cow widt)) 132 | rev exps 133 134 135 ;;; Row Literals ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 136 137 = ({,} st rex err ok) 138 | ok st (rowE | rexKids rex) 139 140 =?= [] v0 141 =?= [3] (v1 3) 142 =?= [3 4] (v2 3 4) 143 =?= 3,4 (v2 3 4) 144 145 146 ;;; Maybe ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 147 148 ;; TODO NONE=0 (SOME x)=[x] 149 150 = NONE | 0 151 = (**SOME x) | 0 x 152 153 = (**maybeCase mb non som) 154 | if isNat-mb non 155 | **som cdr-mb 156 157 (maybe non som mb)=(maybeCase mb non som) 158 159 (isNone x)=(isZero x) 160 (isSome x)=(neq 0 x) 161 162 (fromSome n x)=(maybeCase x n id) 163 164 (unpackSome x)=(**fromSome (die {Unexpected NONE}) x) 165 166 > Bit > Maybe a > Maybe a 167 (**maybeGuardNot check cont)=(if check NONE cont) 168 169 > Bit > Maybe a > Maybe a 170 (**maybeGuard check cont)=(maybeGuardNot (not check) cont) 171 172 =?= 1 | maybeCase SOME-0 0 inc 173 =?= 1 | maybeCase SOME-1 0 id 174 =?= 1 | maybeCase SOME-2 0 dec 175 =?= 1 | maybeCase NONE 1 die 176 177 = (fmapMaybe myb fun) 178 | maybeCase myb NONE 179 & v 180 | SOME | fun v 181 182 =?= SOME-1 | fmapMaybe SOME-0 inc 183 =?= NONE | fmapMaybe NONE inc 184 185 =?= 1 | isSome (SOME 0) 186 =?= 0 | isSome NONE 187 =?= 0 | isNone (SOME 0) 188 =?= 1 | isNone NONE 189 190 191 ;;; Unfolding ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 192 193 ; TODO: Would it be better to just use the list version and then generate 194 ; a row from that? This is a very natural function on lazy lists. 195 196 = (unfoldr f seed) 197 ^ _ 0 seed 198 ? (go idx seed) 199 | maybeCase (f seed) (cow idx) 200 & valSeed 201 | go (inc idx) (snd valSeed) (fst valSeed) 202 203 =?= [0 1 2 3 4 5] 204 ^ unfoldr _ 0 205 & x 206 | if (lte x 5) (SOME [x (inc x)]) NONE 207 208 209 ;;; Tests ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 210 211 =?= [0 1 2] (v3 0 1 2) 212 213 =?= 1 | not (has 1 [2 3 4]) 214 =?= 1 | not (has 1 [2 3 4]) 215 =?= 1 | has 2 [2 3 4] 216 =?= 1 | has 3 [2 3 4] 217 =?= 1 | has 4 [2 3 4] 218 =?= 1 | not (has 5 [2 3 4]) 219 220 =?= (slash [3 4 5] 0 5) | [3 4 5 0 0] 221 =?= (slash [3 4 5] 1 4) | [4 5 0] 222 =?= (slash [3 4 5] 2 3) | [5] 223 =?= (slash [3 4 5] 3 2) | [] 224 225 =?= (slice [3 4 5] 0 5) | [3 4 5] 226 =?= (slice [3 4 5] 1 4) | [4 5] 227 =?= (slice [3 4 5] 2 3) | [5] 228 =?= (slice [3 4 5] 3 2) | [] 229 230 (ADD x y k)=(k x y) 231 232 =?= [5 4 3] | rev ([3 4 5]) 233 =?= [] | rev ([]) 234 235 =?= 12 | sum [3 4 5] 236 =?= 24 | sumOf (mul 2) [3 4 5] 237 =?= [1 2 3 4 5 6 7 8 9] | cat [[] [1] [2 3] [4 5 6] [7 8] [9] []] 238 239 =?= [1 2 3] (rowCons 1 [2 3]) 240 241 =?= [] | take 0 [1 2 3 4] 242 =?= [1] | take 1 [1 2 3 4] 243 =?= [1 2 3 4] | take 4 [1 2 3 4] 244 =?= [1 2 3 4] | take 20 [1 2 3 4] 245 =?= [1 2 3 4] | drop 0 [1 2 3 4] 246 =?= [2 3 4] | drop 1 [1 2 3 4] 247 =?= [4] | drop 3 [1 2 3 4] 248 =?= [] | drop 4 [1 2 3 4] 249 =?= [] | drop 20 [1 2 3 4] 250 251 =?= [1 2 3 4] | drop 0 [1 2 3 4] 252 =?= [] | drop 10 [1 2 3 4] 253 =?= [] | chunks 3 [] 254 =?= [[1]] | chunks 3 [1] 255 =?= [[1 2 3]] | chunks 3 [1 2 3] 256 =?= [[1 2 3] [4]] | chunks 3 [1 2 3 4] 257 258 =?= [0,1,2 3,4,5 6,7,8 [9]] | chunks 3 [0 1 2 3 4 5 6 7 8 9] 259 260 =?= 1 | has {aa} [{aa} {bb}] 261 =?= 1 | not (has {aa} [{bb} {cc}]) 262 263 264 ;;; Lists ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 265 266 = NIL | 0 267 = (**CONS x xs) | [x xs] 268 269 ;; TODO: should {listCase} always be inlined? 270 ;; TODO: Should {listCase} use {isZero} or {isNat} as a termination check? 271 272 = (**listCase xs nil cons) 273 | if isNat-xs nil 274 | **cons idx-0-xs idx-1-xs 275 276 ;; TODO s/([a-z])Singleton/\1Sing/g 277 278 (listSing x)=(CONS x 0) 279 280 = (listMap f l) 281 | listCase l NIL 282 & (x xs) 283 | CONS f-x listMap-f-xs 284 285 (**listForEach l f)=(listMap f l) 286 287 = (listHead l) 288 | listCase l NONE 289 & (h _) 290 | SOME h 291 292 = (listSafeHead fb l) 293 | listCase l fb 294 & (x _) 295 | x 296 297 (listUnsafeHead l)=(fst l) 298 (listUnsafeTail l)=(snd l) 299 300 =?= NONE | listHead NIL 301 =?= SOME-3 | listHead (CONS 3 (CONS 4 NIL)) 302 =?= 3 | listUnsafeHead (CONS 3 (CONS 4 NIL)) 303 =?= CONS-4-NIL | listUnsafeTail (CONS 3 (CONS 4 NIL)) 304 =?= 0 | listUnsafeHead NIL 305 =?= 5 | fromSome 4 (SOME 5) 306 =?= 5 | unpackSome (SOME 5) 307 =?= 4 | fromSome 4 NONE 308 309 = (listIdxCps i xs not_found found) 310 | listCase xs not_found 311 & (x xs) 312 | ifz i (found x) 313 | listIdxCps (dec i) xs not_found found 314 315 (listIdxMb fb i xs)=(listIdxCps i xs NONE SOME) 316 (listIdxOr fb i xs)=(listIdxCps i xs fb id) 317 (listIdx i xs)=(listIdxCps i xs 0 id) 318 319 = (listLastOr fallback xs) 320 | listCase xs fallback 321 & (x xs) 322 | listLastOr x xs 323 324 (listUnsafeLast l)=(listLastOr 0 l) 325 326 = (listLast l) 327 | listCase l NONE 328 & (h t) 329 | SOME | listLastOr h t 330 331 =?= NONE | listLast NIL 332 =?= SOME-3 | listLast (CONS 3 NIL) 333 =?= SOME-4 | listLast (CONS 3 (CONS 4 NIL)) 334 335 336 ;;; Operations With Lists ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 337 338 = (listFoldl f z l) 339 | listCase l z 340 & (x xs) 341 @ fzx (f z x) 342 | seq fzx 343 | listFoldl f fzx xs 344 345 = (listFoldr f z l) 346 | listCase l z 347 & (x xs) 348 | f x (listFoldr f z xs) 349 350 > (a -> a) > List a > a 351 = (listFoldl1 f xs) 352 | listCase xs {listFoldl1}|{empty list} 353 & (x xs) 354 | listFoldl f x xs 355 356 = (listUnfoldr f seed) 357 | maybeCase (f seed) NIL 358 & valSeed 359 | CONS (fst valSeed) 360 | listUnfoldr f (snd valSeed) 361 362 =?= (, 0 , 1 , 2 , 3 , 4 , 5 0) 363 ^ listUnfoldr _ 0 364 & x 365 | if (lte x 5) (SOME [x (inc x)]) NONE 366 367 = (listMap f l) 368 | listCase l NIL 369 & (x xs) 370 | CONS f-x listMap-f-xs 371 372 = (listLen l) | listFoldr (x acc & inc acc) 0 l 373 = (listSum l) | listFoldr add 0 l 374 = (listFromRow v) | foldr CONS NIL v 375 = (listFromRowRev v) | foldrRev CONS NIL v 376 = (listAnd v) | listFoldr and TRUE v 377 = (listOr v) | listFoldr or 0 v 378 = (listAll f v) | listAnd listMap-f-v 379 = (listAny f v) | listOr listMap-f-v 380 = (listHas e xs) | listAny eql-e xs 381 = (listEnumFrom n) | CONS n (listEnumFrom inc-n) 382 = (listRepeat n) | CONS n listRepeat-n 383 = (listAllEql xs) | listCase xs TRUE (x xs)&(listAll (eql x) xs) 384 385 = (listWeld a b) 386 | listCase a b 387 & (x xs) 388 | CONS x (listWeld xs b) 389 390 > List (List a) > List a 391 = (listCat ls) 392 | listCase ls NIL 393 & (x xs) 394 | listWeld x 395 | listCat xs 396 397 (listCatMap f r)=(listCat | listMap f r) 398 399 = (listTake num lis) 400 | ifNot num NIL 401 | listCase lis NIL 402 & (x xs) 403 | CONS x 404 | listTake dec-num xs 405 406 = (listDrop num lis) 407 | ifNot num lis 408 | listCase lis NIL 409 | (x xs & listDrop dec-num xs) 410 411 = (listTakeWhile f lis) 412 | listCase lis NIL 413 & (x xs) 414 | if f-x (CONS x | listTakeWhile f xs) 415 | NIL 416 417 = (listDropWhile f lis) 418 | listCase lis NIL 419 & (x xs) 420 | if f-x listDropWhile-f-xs 421 | lis 422 423 =?= [2 [3 0]] | listTakeWhile id [2 [3 [0 [4 [5 0]]]]] 424 =?= [0 [4 [5 0]]] | listDropWhile id [2 [3 [0 [4 [5 0]]]]] 425 426 = (_SizedListToRow sz l) 427 | listFoldr supply cow-sz 428 | listTake sz (listWeld l listRepeat-0) 429 430 = (_SizedListToRowRev sz l) 431 | listFoldl apply cow-sz 432 | listTake sz (listWeld l listRepeat-0) 433 434 = sizedListToRow | _SizedListToRow 435 = sizedListToRowRev | _SizedListToRowRev 436 = (listToRow l) | sizedListToRow listLen-l l 437 = (listToRowRev l) | sizedListToRowRev listLen-l l 438 439 =?= [1 2 3] | sizedListToRow 3 [1 [2 [3 [4 [5 0]]]]] 440 =?= [1 2 0] | sizedListToRow 3 [1 [2 0]] 441 =?= [] | sizedListToRow 0 [1 [2 [3 0]]] 442 =?= [0 0 0] | sizedListToRow 3 NIL 443 =?= [3 2 1] | sizedListToRowRev 3 [1 [2 [3 [4 [5 0]]]]] 444 =?= [0 2 1] | sizedListToRowRev 3 [1 [2 0]] ; TODO is this behavior good? 445 =?= [] | sizedListToRowRev 0 [1 [2 [3 0]]] 446 =?= [0 0 0] | sizedListToRowRev 3 NIL 447 =?= [1 2 3] | listToRow [1 [2 [3 0]]] 448 =?= [] | listToRow NIL 449 =?= [1 2 3] | listToRowRev [3 [2 [1 0]]] 450 =?= [] | listToRowRev NIL 451 452 = (listZipWith f al bl) 453 | listCase al NIL 454 & (a as) 455 | listCase bl NIL 456 & (b bs) 457 | CONS f-a-b 458 (listZipWith f as bs) 459 460 (listZip a b)=(listZipWith (0 0 3 0) b a) 461 462 =?= | CONS [3 4] | CONS [4 5] NIL 463 | listZip listFromRow-[3 4] listFromRow-[4 5] 464 465 = (listFilter f lis) 466 | listCase lis NIL 467 & (x xs) 468 | if f-x (CONS x | listFilter f xs) 469 | listFilter f xs 470 471 (listIsEmpty xs)=(isNat xs) 472 473 = (listMinimumOn f a bs) 474 | listCase bs a 475 & (x xs) 476 | listMinimumOn f 477 | if (lth f-x f-a) x a 478 | xs 479 480 = (listGen n f) 481 ^ _ 0 482 ? (loop i) 483 | if (eql i n) NIL 484 | CONS (f i) 485 | loop (inc i) 486 487 =?= (listGen 3 id) [0 [1 [2 0]]] 488 489 (listRep i n)=(listGen n (const i)) 490 491 =?= (listRep 9 3) [9 [9 [9 0]]] 492 =?= (listRep 9 3) (listFromRow | rep 9 3) 493 494 ;; {listSortBy}, {listSort}, {sortBy}, {sort} etc are simple 495 ;; implementations meant to be used in jets. If you want a proper 496 ;; quicksort or mergesort, implement them yourself. 497 498 = (listInsertBy cmp x lis) 499 | listCase lis (listSing x) 500 & (y ys) 501 | if (cmp x y) 502 | CONS y (listInsertBy cmp x ys) 503 | CONS x lis 504 505 ;; {listUniq} removes duplicate values that appear next to each-other. 506 ;; If the input is sorted, then the output will have no duplicates. 507 508 = (listUniq xs) 509 | ifz xs NIL 510 ^ _ (fst xs) (snd xs) 511 ? (go x ys) 512 | listCase ys (listSing x) 513 & (y ys) 514 | if (eql x y) (go y ys) 515 | CONS x (go y ys) 516 517 = (listNub xs) 518 | listCase xs NIL 519 & (x xs) 520 | CONS x (listNub (listFilter neq-x xs)) 521 522 = (listIterate f x) 523 | (CONS x (listIterate f (f x))) 524 525 = (listSortBy cmp xs) | listFoldr (listInsertBy cmp) NIL xs 526 = (listSort xs) | listSortBy cmp xs 527 = (listSortUniq xs) | listUniq (listSort xs) 528 = (comparing f x y) | cmp (f x) (f y) 529 530 = (listSortOn f lis) 531 | listMap snd 532 | listSortBy (comparing fst) 533 | listMap x&(y @ f x)(seq y (y, x)) 534 | lis 535 536 ;; {rowPort} converts from a list operation to a row operation. 537 538 = (rowPort op row) | listToRow (op | listFromRow row) 539 = (uniq row) | rowPort listUniq row 540 = (sortOn f row) | rowPort (listSortOn f) row 541 = (sortBy cmp row) | rowPort (listSortBy cmp) row 542 = (sort row) | rowPort listSort row 543 = (sortUniq row) | rowPort listSortUniq row 544 545 =?= [0 3 3 4 5] | sort | [0 3 4 3 5] 546 =?= [0 3 3 4 5] | sortBy cmp | [0 3 4 3 5] 547 =?= [5 4 3 3 0] | sortBy (flip cmp) | [0 3 4 3 5] 548 =?= [0 3 4 3 5] | sortBy _&EQ | [0 3 4 3 5] 549 =?= [5 4 3 3 0] | sortOn x&(sub 5 x) | [0 3 4 3 5] 550 =?= [5 3 4 3 0] | sortOn not | [0 3 4 3 5] 551 =?= [0 5 3 4 3] | sortOn bit | [0 3 4 3 5] 552 =?= [0 5 0] | uniq [0 0 5 5 0 0] 553 =?= [0 5] | sortUniq [0 0 5 5 0 0] 554 555 556 ;;; Searching ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 557 558 (listIndexed l)=(listZip (listEnumFrom 0) l) 559 560 = (listIsPrefixOf xs ys) 561 | listCase xs TRUE 562 & (x xs) 563 | listCase ys FALSE 564 & (y ys) 565 | and (eql x y) 566 | listIsPrefixOf xs ys 567 568 ; > (List a > Bool) 569 ; > List a 570 ; > List (Int, List a) 571 = (listSearch f xs) 572 ^ (_ 0 xs) 573 ? (go off xs) 574 | seq off 575 @ rest | listCase xs NIL 576 & (_ xs) 577 | go (inc off) xs 578 | if (f xs) | CONS [off xs] rest 579 | else | rest 580 581 ; > List a > List a > List (Int, List a) 582 = (listSubstringSearch needle haystack) 583 | listSearch (listIsPrefixOf needle) haystack 584 585 = (listFindIndex pred xs notFound found) 586 ^ listFoldr _ notFound (listIndexed xs) 587 & (idxVal rest) 588 | ifNot (pred | snd idxVal) rest 589 | found (fst idxVal) 590 591 = (listElemIndex e xs not_found found) 592 | listFindIndex (eql e) xs not_found found 593 594 (listElemIndexOpt x xs)=(listElemIndex x xs NONE SOME) 595 596 = (findIdx p row nf f) | listFindIndex p (listFromRow row) nf f 597 = (elemIdx e row nf f) | findIdx (eql e) row nf f 598 599 = (span pred row) 600 | findIdx (compose not pred) row (row,[]) (flip splitAt row) 601 602 = (filter f row) | rowPort (listFilter f) row 603 = (delete val row) | filter (neq val) row 604 605 = (findIdxMany f row) 606 ^ listFoldr _ NIL (listIndexed | listFromRow row) 607 & (idxVal rest) 608 | ifNot (f | snd idxVal) rest 609 | CONS (fst idxVal) rest 610 611 (elemIdxMany key row)=(findIdxMany (eql key) row) 612 613 =?= (| listToRow | listIndexed | listFromRow [{a} {b} {c}]) 614 [[0 {a}] [1 {b}] [2 {c}]] 615 616 =?= SOME-0 | elemIdx 5 [5 6 7] NONE SOME 617 =?= SOME-1 | elemIdx 6 [5 6 7] NONE SOME 618 =?= SOME-2 | elemIdx 7 [5 6 7] NONE SOME 619 =?= NONE | elemIdx 8 [5 6 7] NONE SOME 620 621 =?= ( [], [2 4 5 6] ) | span lte-9 [2 4 5 6] 622 =?= ( [2 4 5 6], [] ) | span gth-9 [2 4 5 6] 623 =?= ( [2], [4 5 6] ) | span eql-2 [2 4 5 6] 624 =?= ( [2 4], [5 6] ) | span even [2 4 5 6] 625 =?= ( [], [2 4 5 6] ) | span odd [2 4 5 6] 626 627 =?= (0 0) | listElemIndex 0 (, 0 , 1 , 2 , 3 0) NONE SOME 628 =?= (0 1) | listElemIndex 1 (, 0 , 1 , 2 , 3 0) NONE SOME 629 =?= (0 2) | listElemIndex 2 (, 0 , 1 , 2 , 3 0) NONE SOME 630 =?= (0 3) | listElemIndex 3 (, 0 , 1 , 2 , 3 0) NONE SOME 631 =?= 0 | listElemIndex 4 (, 0 , 1 , 2 , 3 0) NONE SOME 632 633 =?= [0 2] 634 | listToRow | elemIdxMany 5 [5 0 5] 635 636 =?= [2 0] 637 | listMap fst 638 | listSubstringSearch (, 2 , 3 0) (listTake 10 | listEnumFrom 0) 639 640 =?= 0 641 | listSubstringSearch (, 3 , 2 0) (listTake 10 | listEnumFrom 0) 642 643 =?= (listTake 11 | listEnumFrom 0) 644 | listMap fst 645 | listSearch (const TRUE) (listTake 10 | listEnumFrom 0) 646 647 =?= 0 648 | listSearch (const FALSE) (listTake 10 | listEnumFrom 0) 649 650 651 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 652 653 = (listIntersperse sep xs) 654 | listCase xs xs 655 & (x xs) 656 ^ CONS x (_ xs) 657 ? (go xs) 658 | listCase xs xs 659 & (x xs) 660 | CONS sep 661 | CONS x 662 | go xs 663 664 =?= [] | listToRow | listIntersperse 0 | listFromRow [] 665 =?= [1] | listToRow | listIntersperse 0 | listFromRow [1] 666 =?= [1 0 2] | listToRow | listIntersperse 0 | listFromRow [1 2] 667 =?= [1 0 2 0 3] | listToRow | listIntersperse 0 | listFromRow [1 2 3] 668 669 =?= [] | intersperse 0 [] 670 =?= [1] | intersperse 0 [1] 671 =?= [1 0 2] | intersperse 0 [1 2] 672 =?= [1 0 2 0 3] | intersperse 0 [1 2 3] 673 674 (listRev xs)=(listFoldl (flip CONS) NIL xs) 675 676 = (listSnoc xs e) 677 | listCase xs (CONS e NIL) 678 & (x xs) 679 | CONS x 680 | listSnoc xs e 681 682 =?= (, 3 , 4 , 5 NIL) 683 | listRev (, 5 , 4 , 3 NIL) 684 685 =?= (listSnoc [0 [1 0]] 2) 686 | [0 [1 [2 0]]] 687 688 = (listProd xs ys) 689 | listCat 690 ^ listFoldl _ NIL listRev-xs 691 & (acc x) 692 ^ CONS (listFoldl _ NIL listRev-ys) acc 693 & (acc y) 694 | CONS (x, y) acc 695 696 =?= (listProd [1 [2 0]] [3 [4 0]]) 697 | [[1 3] [[1 4] [[2 3] [[2 4] 0]]]] 698 699 700 ;;; Either ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 701 702 = (**LEFT x) [0 x] 703 = (**RIGHT x) [1 x] 704 705 = (**eitherCase x l r) (if (idx 0 x) (**r idx-1-x) (**l idx-1-x)) 706 = (fromRight l x) (eitherCase x l id) 707 = (unpackRight x) (**fromRight (die {Unexpected LEFT}) x) 708 = (**eitherCaseLeft x r l) (if (idx 0 x) (**r idx-1-x) (**l idx-1-x)) 709 = (eitherOpen x r) (eitherCase x _&x r) 710 = (eitherOpenLeft x l) (eitherCase x l _&x) 711 = (fromLeft r x) (eitherCase x id r) 712 = (unpackLeft x) (**fromLeft (die {Unexpected RIGHT}) x) 713 = (eitherGetRight x k) (eitherCase x _&x k) 714 = (eitherGetLeft x k) (eitherCase x k _&x) 715 = (eitherMap f val) (eitherCase val 0 (x & 1 f-x)) 716 = (eitherBind val f) (eitherCase val _&val f) 717 718 =?= 1 | eitherCase RIGHT-0 const-0 inc 719 =?= 1 | eitherCase RIGHT-1 const-0 id 720 =?= 1 | eitherCase RIGHT-2 const-0 dec 721 =?= 1 | eitherCase LEFT-9 const-1 die 722 =?= 1 | eitherCase LEFT-1 id die 723 =?= 1 | eitherCase LEFT-0 inc die 724 725 =?= 1 | unpackRight (RIGHT 1) 726 =?= 1 | unpackLeft (LEFT 1) 727 728 > Row (Eat a b) > (Row a, Row b) 729 = (partition r) 730 ^ map listToRow (foldr _ [NIL NIL] r) 731 & (x i) 732 @ lefts | fst i 733 @ rights | snd i 734 | if (fst x) 735 | (lefts, CONS (snd x) rights) 736 | else 737 | (CONS (snd x) lefts, rights) 738 739 =?= [[0 3] [1 2]] 740 | partition [LEFT-0 RIGHT-1 RIGHT-2 LEFT-3] 741 742 743 ;;; Maybe utils that depend on list ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 744 745 = (listCatMaybes top) 746 | listCase top NIL 747 & (mX xs) 748 | maybeCase mX (listCatMaybes xs) 749 & x 750 | CONS x (listCatMaybes xs) 751 752 = (mapMaybe law row) 753 ^ _ NIL 0 len-row 754 ? (go acc kept remain) 755 | ifz remain 756 | sizedListToRow kept acc 757 @ ix (dec remain) 758 | maybeCase (law | idx ix row) 759 | go acc kept ix 760 & item 761 | go (CONS item acc) (inc kept) ix 762 763 = (catMaybes lis) | listToRow (listCatMaybes (listFromRow lis)) 764 = (listMapMaybe f lis) | listCatMaybes (listMap f lis) 765 766 =?= [1 [2 0]] | listCatMaybes [SOME-1 [SOME-2 0]] 767 =?= [1 [2 0]] | listCatMaybes [SOME-1 [SOME-2 [NONE 0]]] 768 =?= [1 [2 0]] | listCatMaybes [SOME-1 [NONE [SOME-2 [NONE 0]]]] 769 =?= [1 [2 0]] | listCatMaybes [NONE [SOME-1 [NONE [SOME-2 [NONE 0]]]]] 770 771 =?= [1 2] | catMaybes ( SOME 1 , SOME 2 ) 772 =?= [1 2] | catMaybes ( SOME 1 , SOME 2 , NONE ) 773 =?= [1 2] | catMaybes ( SOME 1 , NONE , SOME 2 , NONE ) 774 =?= [1 2] | catMaybes ( NONE , SOME 1 , NONE , SOME 2 ) 775 776 =?= [2 4 6] | (mapMaybe _ [1 2 3 4 5 6])^(x & if (even x) SOME-x NONE) 777 =?= [1 4 5] | catMaybes [SOME-1 NONE SOME-4 SOME-5 NONE] 778 779 780 ;;; Tall-Form Row Literals ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 781 782 openRowExpect={Expected something like (++ x), (++ f x y), etc} 783 784 = (readOpenRow readExp rex err ok) 785 @ topRune (rexRune rex) 786 ^ _ NIL rex 787 ? (go acc rex) 788 @ sons (rexSons rex) 789 @ heir (rexHeir rex) 790 @ rune (rexRune rex) 791 | ifz rex 792 | ok (listToRowRev acc) 793 | if (neq topRune rune) 794 | readExp rex err exp&(go (CONS exp acc) 0) 795 | if (null sons) 796 | err rex openRowExpect 797 @ itemRex 798 | if (eql 1 | len sons) (idx 0 sons) 799 | OPEN {|} sons 0 800 | readExp itemRex err 801 & exp 802 @ acc (CONS exp acc) 803 | seq acc 804 | go acc heir 805 806 (readRex rex err ok)=(ok rex) 807 808 = ({++} st rex err ok) 809 | readOpenRow readRex rex err 810 & res 811 | ok st (rowE res) 812 813 =?= [3 4 5] (++ 3)(++ 4)(++ 5) 814 =?= [3 4 5] (++ 3)(++ 4)5 815 =?= [3 4 5] (++3)(++ 3 3)5 816 817 =?= [3 4 5] 818 ++ 3 819 ++ 4 820 ++ 5 821 822 =?= [3 4 5] 823 ++ 3 824 ++ 4 825 ++ 5 826 827 828 ;;; Binary Search ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 829 830 ;; {bsearch} finds the index of an item within a "row set". The input 831 ;; row is presumed to be in ascending order and without duplciates. 832 ;; 833 ;; {bsearch} finds the index of an item equal to the target, or the 834 ;; index of the smallest item larger than the target, or it returns the 835 ;; length of the array, if no such item exists. 836 ;; 837 ;; The result is tagged to indicate if the result is a match or not. 838 ;; Tagging works by left-shifting the resuilt by one, and then setting the 839 ;; low bit only if there was a match. 840 ;; 841 ;; The index returned in the "not found" case is always the index where 842 ;; this item could be inserted without breaking the "row set" invariants. 843 ;; 844 ;; {lsearch} has the same behavior as {bsearch}, and mostly just exists 845 ;; as a test case. 846 847 (**found ix)=(inc | lsh ix 1) 848 (**not_found ix)=(lsh ix 1) 849 850 > Any > Row Any > Nat > Nat > Nat 851 = (lsearch_ key row low end) 852 | if (gte low end) (not_found low) 853 | switch (cmp key | get row low) 0 854 ++ not_found low ; LT 855 ++ found low ; EQ 856 ++ lsearch_ key row (inc low) end ; GT 857 858 > Any > Row Any > Nat 859 = (bsearch_ key row low end) 860 | if (gte low end) (not_found low) 861 @ index (rsh (add low end) 1) 862 | switch (cmp key | get row index) 0 863 ++ bsearch_ key row low index ; LT 864 ++ found index ; EQ 865 ++ bsearch_ key row (inc index) end ; GT 866 867 (lsearch key row)=(lsearch_ key row 0 (len row)) 868 (bsearch key row)=(bsearch_ key row 0 (len row)) 869 870 = (search_chk row assoc) 871 ^ foldr _ TRUE assoc 872 & (kv continue) 873 @ k (fst kv) 874 @ e (snd kv) 875 @ lr (lsearch k row) 876 @ br (bsearch k row) 877 | if (neq e lr) [{lsearch mismatch} [{for key} k] [e {!=} lr]] 878 | if (neq e br) [{bsearch mismatch} [{for key} k] [e {!=} br]] 879 | continue 880 881 N=not_found 882 F=found 883 884 =?= 1 | search_chk [] | rowIndexed [N|0 N|0 N|0] 885 =?= 1 | search_chk [1] | rowIndexed [N|0 F|0 N|1] 886 =?= 1 | search_chk [1 3 5] | rowIndexed [N|0 F|0 N|1 F|1 N|2 F|2 N|3 N|3] 887 =?= 1 | search_chk [1 3 5 7] | rowIndexed [N|0 F|0 N|1 F|1 N|2 F|2 N|3 F|3 N|4] 888 =?= 1 | search_chk [1 3 5 6] | rowIndexed [N|0 F|0 N|1 F|1 N|2 F|2 F|3 N|4 N|4] 889 890 891 ;;; Traversing Lists ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 892 893 > (a > (b>r)) > Row a > m (Row b) 894 = (traverseList f xs return) 895 ^ _ NIL xs 896 ? (go acc remain) 897 | listCase remain 898 (return (listRev acc)) 899 & (head tail) 900 | f head 901 & newHead 902 | go (CONS newHead acc) tail 903 904 =?= 0 | traverseList (x ret)&(if even-x ret-x 0) [3 [4 0]] id 905 =?= 0 | traverseList (x ret)&(if even-x ret-x 0) [4 [5 0]] id 906 =?= [4 [6 0]] | traverseList (x ret)&(if even-x ret-x 0) [4 [6 0]] id 907 908 > st 909 > (st > b > r) 910 > List a 911 > m st (List b) 912 = (listTraverseState st f xs return) 913 ^ _ st NIL xs 914 ? (go st acc remain) 915 | listCase remain (return st (listRev acc)) 916 & (head tail) 917 | f st head 918 & (st newHead) 919 @ acc (CONS newHead acc) 920 | go st acc tail 921 922 =?= 17,(, 3 , 4 , 5 0) 923 ^ listTraverseState 5 _ [3 [4 [5 0]]] v2 924 ? (step st item pure) 925 | pure (add st item) item 926 927 928 ;;; Traversing Rows ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 929 930 > (a > (b>r)) > Row a > m (Row b) 931 = (rowTraverse f xs return) 932 | traverseList f (listFromRow xs) 933 & out 934 | return (listToRow out) 935 936 =?= 0 | rowTraverse (x ret)&(if even-x ret-x 0) [3 4] id 937 =?= 0 | rowTraverse (x ret)&(if even-x ret-x 0) [4 5] id 938 =?= [4 6] | rowTraverse (x ret)&(if even-x ret-x 0) [4 6] id 939 940 941 > st > (a > (st>b>r)) > Row a > m st (Row b) 942 = (rowTraverseState st f xs return) 943 | listTraverseState st f (listFromRow xs) 944 & (st out) 945 | return st (listToRow out) 946 947 =?= 17,[4 5 6] 948 ^ rowTraverseState 5 _ [3 4 5] v2 949 ? (step st item pure) 950 | pure (add st item) (inc item) 951 952 953 ;;; Exports ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 954 955 ^-^ 956 ^-^ slash slice chunks rep rowCons rowSnoc 957 ^-^ rowIndexed findIdx elemIdx has 958 ^-^ rowAnd rowOr sum sumOf all any zip zipWith 959 ^-^ cat catMap 960 ^-^ take drop rev 961 ^-^ unfoldr span splitAt foldr1 strictRow seqRow insert 962 ^-^ 963 ^-^ bopE bapE bowE appE rowE 964 ^-^ {,} 965 ^-^ 966 ^-^ NONE SOME maybeCase maybe 967 ^-^ fromSome unpackSome 968 ^-^ isSome isNone fmapMaybe 969 ^-^ maybeGuard maybeGuardNot 970 ^-^ 971 ^-^ mapMaybe catMaybes 972 ^-^ listMapMaybe listCatMaybes 973 ^-^ 974 ^-^ NIL CONS 975 ^-^ listCase 976 ^-^ listSing 977 ^-^ listMap listForEach 978 ^-^ listHead listSafeHead listUnsafeHead listUnsafeTail 979 ^-^ listIdxCps listIdxOr listIdx 980 ^-^ listLastOr listUnsafeLast listLast 981 ^-^ 982 ^-^ listFoldl listFoldl1 983 ^-^ listFoldr 984 ^-^ listLen sizedListToRow sizedListToRowRev 985 ^-^ listToRow listFromRow 986 ^-^ listToRowRev listFromRowRev 987 ^-^ listAnd listOr listSum listAll listAllEql listAny 988 ^-^ listHas listEnumFrom listWeld listCat listCatMap listTake listDrop 989 ^-^ listTakeWhile listDropWhile 990 ^-^ listZipWith listZip listFilter listIsEmpty listMinimumOn listSortOn 991 ^-^ listNub listIterate 992 ^-^ listGen listRep listFindIndex listElemIndex listElemIndexOpt 993 ^-^ listIsPrefixOf listSearch listSubstringSearch 994 ^-^ listIndexed 995 ^-^ intersperse listIntersperse 996 ^-^ listRev listSnoc listProd 997 ^-^ 998 ^-^ LEFT RIGHT 999 ^-^ fromLeft unpackLeft 1000 ^-^ fromRight unpackRight 1001 ^-^ eitherCase eitherOpen 1002 ^-^ eitherOpenLeft eitherCaseLeft 1003 ^-^ eitherGetRight eitherGetLeft 1004 ^-^ eitherMap eitherBind partition 1005 ^-^ 1006 ^-^ sort sortBy sortOn sortUniq 1007 ^-^ filter delete 1008 ^-^ findIdxMany elemIdxMany 1009 ^-^ 1010 ^-^ readRex 1011 ^-^ readOpenRow 1012 ^-^ {++} 1013 ^-^ 1014 ^-^ lsearch lsearch_ 1015 ^-^ bsearch bsearch_ 1016 ^-^ 1017 ^-^ traverseList listTraverseState 1018 ^-^ rowTraverse rowTraverseState 1019 ^-^ 1020 ^-^ {>} {#typedef} {\} 1021 ^-^