plunder

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 ^-^