28 | record ChunkSize where
32 | {auto 0 prf : IsSucc size}
36 | CS x == CS y = x == y
40 | compare (CS x) (CS y) = compare x y
43 | Show ChunkSize where
47 | fromInteger : (n : Integer) -> ChunkSize
49 | case cast {to = Nat} n of
53 | public export %inline %hint
54 | defaultChunkSize : ChunkSize
55 | defaultChunkSize = 128
62 | data SplitRes : Type -> Type where
63 | Middle : (pre, post : c) -> SplitRes c
64 | All : Nat -> SplitRes c
71 | interface Monoid c => Chunk (0 c,o : Type) | c where
72 | unfoldChunk : ChunkSize => (s -> Either r (o,s)) -> s -> UnfoldRes r s c
73 | replicateChunk : ChunkSize => o -> c
75 | unconsChunk : c -> Maybe (o, Maybe c)
76 | splitChunkAt : Nat -> c -> SplitRes c
77 | breakChunk : BreakInstruction -> (o -> Bool) -> c -> BreakRes c
78 | filterChunk : (o -> Bool) -> c -> Maybe c
81 | nonEmpty : Chunk c o => c -> Maybe c
82 | nonEmpty v = if isEmpty v then Nothing else Just v
90 | unfold : ChunkSize => Chunk c o => s -> (s -> Either r (o,s)) -> Pull f c es r
91 | unfold init g = P.unfold init (unfoldChunk g)
95 | fill : ChunkSize => (0 c : _) -> Chunk c o => o -> Pull f c es ()
96 | fill _ v = P.fill (replicateChunk v)
100 | iterate : ChunkSize => (0 c : _) -> Chunk c o => o -> (o -> o) -> Pull f c es ()
101 | iterate _ v f = unfold v (\x => Right (x, f x))
105 | replicate : ChunkSize => (0 c : _) -> Chunk c o => Nat -> o -> Stream f es c
107 | Chunk.unfold n $
\case
115 | parameters {auto chnk : Chunk c o}
119 | uncons : Pull f c es r -> Pull f q es (Either r (o, Pull f c es r))
121 | assert_total $
P.uncons p >>= \case
122 | Left x => pure (Left x)
123 | Right (vs,q) => case unconsChunk vs of
124 | Just (el,rem) => pure $
Right (el,consMaybe rem q)
125 | Nothing => Chunk.uncons q
129 | splitAt : Nat -> Pull f c es r -> Pull f c es (Pull f c es r)
130 | splitAt 0 p = pure p
132 | assert_total $
P.uncons p >>= \case
133 | Left v => pure (pure v)
134 | Right (vs,q) => case splitChunkAt k vs of
135 | Middle pre post => cons pre (pure $
cons post q)
136 | All n => cons vs (Chunk.splitAt n q)
140 | take : Nat -> Pull f c es r -> Pull f c es ()
141 | take 0 = const $
pure ()
142 | take n = ignore . newScope . Chunk.splitAt n
148 | limit : Has e es => Lazy e -> Nat -> Pull f c es r -> Pull f c es r
150 | q <- Chunk.splitAt n p
151 | Left v <- peekRes q | Right _ => throw err
157 | drop : Nat -> Pull f c es r -> Pull f c es r
158 | drop k p = join $
drain (Chunk.splitAt k p)
162 | head : Pull f c es r -> Pull f c es ()
163 | head = Chunk.take 1
167 | tail : Pull f c es r -> Pull f c es r
168 | tail = Chunk.drop 1
181 | (orElse : r -> Pull f c es r)
182 | -> BreakInstruction
185 | -> Pull f c es (Pull f c es r)
186 | breakFull orElse bi pred = breakPull orElse (breakChunk bi pred)
192 | {auto has : Has e es}
194 | -> BreakInstruction
197 | -> Pull f c es (Pull f c es r)
198 | forceBreakFull err = breakFull (const $
throw err)
205 | takeUntil : BreakInstruction -> (o -> Bool) -> Pull f c es r -> Stream f es c
206 | takeUntil tf pred = ignore . newScope . Chunk.breakFull pure tf pred
211 | takeWhile : (o -> Bool) -> Pull f c es r -> Stream f es c
212 | takeWhile pred = Chunk.takeUntil DropHit (not . pred)
216 | takeThrough : (o -> Bool) -> Pull f c es r -> Stream f es c
217 | takeThrough pred = Chunk.takeUntil TakeHit (not . pred)
224 | dropUntil : BreakInstruction -> (o -> Bool) -> Pull f c es r -> Pull f c es r
225 | dropUntil tf pred p = drain (Chunk.breakFull pure tf pred p) >>= id
230 | dropWhile : (o -> Bool) -> Pull f c es r -> Pull f c es r
231 | dropWhile pred = Chunk.dropUntil PostHit (not . pred)
236 | dropThrough : (o -> Bool) -> Pull f c es r -> Pull f c es r
237 | dropThrough pred = Chunk.dropUntil DropHit (not . pred)
242 | split : (o -> Bool) -> Pull f c es r -> Pull f (List c) es r
243 | split pred = scanFull neutral impl (map pure . nonEmpty)
245 | loop : SnocList c -> Maybe c -> (Maybe $
List c, c)
246 | loop sc Nothing = (Just $
sc <>> [], neutral)
248 | assert_total $
case breakChunk DropHit pred x of
249 | Broken x post => loop (sc :< fromMaybe neutral x) post
250 | Keep x => (Just $
sc <>> [], x)
252 | impl : c -> c -> (Maybe $
List c, c)
254 | case breakChunk DropHit pred cur of
255 | Broken x post => loop [<pre <+> fromMaybe neutral x] post
256 | Keep x => (Nothing, pre <+> x)
262 | nel : List a -> Maybe (List a)
268 | mapMaybe : (o -> Maybe p) -> Pull f (List o) es r -> Pull f (List p) es r
269 | mapMaybe f = P.mapMaybe (nel . mapMaybe f)
273 | filter : Chunk c o => (o -> Bool) -> Pull f c es r -> Pull f c es r
274 | filter = P.mapMaybe . filterChunk
278 | filterNot : Chunk c o => (o -> Bool) -> Pull f c es r -> Pull f c es r
279 | filterNot pred = Chunk.filter (not . pred)
283 | mapOutput : Functor t => (o -> p) -> Pull f (t o) es r -> Pull f (t p) es r
284 | mapOutput = P.mapOutput . map
290 | parameters {auto fld : Foldable t}
293 | fold : (p -> o -> p) -> p -> Pull f (t o) es r -> Pull f p es r
294 | fold g = P.fold (foldl g)
299 | foldPair : (p -> o -> p) -> p -> Pull f (t o) es r -> Pull f q es (p,r)
300 | foldPair g = P.foldPair (foldl g)
304 | foldGet : (p -> o -> p) -> p -> Stream f es (t o) -> Pull f q es p
305 | foldGet g = P.foldGet (foldl g)
309 | fold1 : Chunk (t o) o => (o -> o -> o) -> Pull f (t o) es r -> Pull f o es r
311 | Chunk.uncons s >>= \case
313 | Right (v,q) => Chunk.fold g v q
318 | all : (o -> Bool) -> Pull f (t o) es r -> Stream f es Bool
319 | all pred = P.all (all pred)
324 | any : (o -> Bool) -> Pull f (t o) es r -> Stream f es Bool
325 | any pred = P.any (any pred)
329 | sum : Num o => Pull f (t o) es r -> Pull f o es r
330 | sum = Chunk.fold (+) 0
334 | count : Pull f (t o) es r -> Pull f Nat es r
335 | count = Chunk.fold (const . S) 0
339 | maximum : Chunk (t o) o => Ord o => Pull f (t o) es r -> Pull f o es r
340 | maximum = Chunk.fold1 max
344 | minimum : Chunk (t o) o => Ord o => Pull f (t o) es r -> Pull f o es r
345 | minimum = Chunk.fold1 min
349 | mappend : Chunk (t o) o => Semigroup o => Pull f (t o) es r -> Pull f o es r
350 | mappend = Chunk.fold1 (<+>)
358 | foldMap : Monoid m => (o -> m) -> Pull f (t o) es r -> Pull f m es r
359 | foldMap f = Chunk.fold (\v,el => v <+> f el) neutral
366 | interface Functor f => Scan f where
367 | scanChunk : (s -> o -> (p,s)) -> s -> f o -> (f p, s)
369 | escanChunk : (s -> o -> Either e (p,s)) -> s -> f o -> Either e (f p, s)
371 | parameters {auto sca : Scan t}
376 | scan : s -> (s -> o -> (p,s)) -> Pull f (t o) es r -> Pull f (t p) es r
377 | scan ini f = P.scan ini (scanChunk f)
381 | scanReturn : s -> (s -> o -> (p,s)) -> Stream f es (t o) -> Pull f (t p) es s
382 | scanReturn ini f = P.scanReturn ini (scanChunk f)
388 | -> (s -> o -> Result es (p,s))
389 | -> Stream f es (t o)
390 | -> Pull f (t p) es s
391 | escanReturn ini f = P.escanReturn ini (escanChunk f)
397 | zipWithScan : p -> (p -> o -> p) -> Pull f (t o) es r -> Pull f (t (o,p)) es r
398 | zipWithScan vp fun =
399 | Chunk.scan vp $
\vp1,vo => let vp2 := fun vp1 vo in ((vo, vp1),vp2)
403 | zipWithScan1 : p -> (p -> o -> p) -> Pull f (t o) es r -> Pull f (t (o,p)) es r
404 | zipWithScan1 vp fun =
405 | Chunk.scan vp $
\vp1,vo => let vp2 := fun vp1 vo in ((vo, vp2),vp2)
409 | zipWithIndex : Pull f (t o) es r -> Pull f (t (o,Nat)) es r
410 | zipWithIndex = Chunk.zipWithScan 0 (\n,_ => S n)
414 | zipWithCount : Pull f (t o) es r -> Pull f (t (o,Nat)) es r
415 | zipWithCount = Chunk.zipWithScan 1 (\n,_ => S n)
419 | runningCount : Pull f (t o) es r -> Pull f (t Nat) es r
420 | runningCount = Chunk.scan 1 (\n,_ => (n, S n))
427 | len : SnocList a -> Maybe (List a)
428 | len = nel . (<>> [])
430 | broken : SnocList a -> List a -> BreakRes (List a)
431 | broken sx xs = Broken (len sx) (nel xs)
436 | -> (s -> Either r (o,s))
438 | -> UnfoldRes r s (List o)
439 | unfoldList sx 0 f x = More (sx <>> []) x
440 | unfoldList sx (S k) f x =
442 | Right (v,x2) => unfoldList (sx:<v) k f x2
443 | Left res => Last res (sx <>> [])
445 | splitAtList : SnocList o -> Nat -> List o -> SplitRes (List o)
446 | splitAtList sx (S k) (h::t) = splitAtList (sx :< h) k t
447 | splitAtList sx n [] = All n
448 | splitAtList sx 0 xs = Middle (sx <>> []) xs
452 | -> BreakInstruction
455 | -> BreakRes (List a)
456 | breakList sx b f [] = Keep (sx <>> [])
457 | breakList sx b f (x :: xs) =
460 | TakeHit => broken (sx :< x) xs
461 | PostHit => broken sx (x::xs)
462 | DropHit => broken sx xs
463 | False => breakList (sx :< x) b f xs
466 | Chunk (List a) a where
467 | unfoldChunk @{CS (S n)} f x =
469 | Left res => Done res
470 | Right (v,x2) => unfoldList [<v] n f x2
472 | replicateChunk @{CS n} = List.replicate n
477 | unconsChunk [] = Nothing
478 | unconsChunk (h::t) = Just (h, nel t)
480 | splitChunkAt = splitAtList [<]
482 | breakChunk = breakList [<]
484 | filterChunk pred = nel . filter pred
486 | scanListImpl : SnocList p -> (s -> o -> (p,s)) -> s -> List o -> (List p,s)
487 | scanListImpl sx f v [] = (sx <>> [], v)
488 | scanListImpl sx f v (x :: xs) =
489 | let (vp,v2) := f v x
490 | in scanListImpl (sx :< vp) f v2 xs
494 | -> (s -> o -> Either e (p,s))
497 | -> Either e (List p,s)
498 | escanListImpl sx f v [] = Right (sx <>> [], v)
499 | escanListImpl sx f v (x :: xs) =
500 | let Right (vp,v2) := f v x | Left x => Left x
501 | in escanListImpl (sx :< vp) f v2 xs
505 | scanChunk = scanListImpl [<]
506 | escanChunk = escanListImpl [<]
513 | data ZipRes : (a,b,c : Type) -> Type where
514 | ZB : List c -> ZipRes a b c
515 | ZL : List a -> List c -> ZipRes a b c
516 | ZR : List b -> List c -> ZipRes a b c
518 | zipImpl : SnocList c -> (a -> b -> c) -> List a -> List b -> ZipRes a b c
519 | zipImpl sx f (x::xs) (y::ys) = zipImpl (sx :< f x y) f xs ys
520 | zipImpl sx f [] [] = ZB (sx <>> [])
521 | zipImpl sx f xs [] = ZL xs (sx <>> [])
522 | zipImpl sx f [] ys = ZR ys (sx <>> [])
525 | (this : Stream f es (List o1))
526 | -> (that : Stream f es (List o2))
527 | -> (k1 : ZipWithLeft f es (List o1) (List o3))
528 | -> (k2 : ZipWithLeft f es (List o2) (List o3))
529 | -> (k3 : Stream f es (List o2) -> Stream f es (List o3))
530 | -> (fun : o1 -> o2 -> o3)
531 | -> Stream f es (List o3)
532 | zipWith_ this that k1 k2 k3 fun = do
533 | Just l1 <- stepLeg this | Nothing => k3 that
534 | Just l2 <- stepLeg that | Nothing => k1 l1.out l1.pull
538 | go : StepLeg f es (List o1) -> StepLeg f es (List o2) -> Stream f es (List o3)
540 | case zipImpl [<] fun l1.out l2.out of
543 | Just l12 <- step l1 | Nothing => k3 l2.pull
544 | Just l22 <- step l2 | Nothing => k1 l12.out l12.pull
545 | assert_total $
go l12 l22
548 | Just l22 <- step l2 | Nothing => k1 as l1.pull
549 | assert_total $
go ({out := as} l1) l22
552 | Just l12 <- step l1 | Nothing => k2 bs l2.pull
553 | assert_total $
go l12 ({out := bs} l2)
562 | -> (o1 -> o2 -> o3)
563 | -> (this : Stream f es (List o1))
564 | -> (that : Stream f es (List o2))
565 | -> Stream f es (List o3)
566 | zipAllWith pad1 pad2 fun this that =
567 | let kL := Chunk.mapOutput (`fun` pad2)
568 | kR := Chunk.mapOutput (fun pad1)
569 | k1 := \x,y => emit (map (`fun` pad2) x) >> kL y
570 | k2 := \x,y => emit (map (fun pad1) x) >> kR y
571 | in zipWith_ this that k1 k2 kR fun
578 | -> (this : Stream f es (List o1))
579 | -> (that : Stream f es (List o2))
580 | -> Stream f es (List (o1,o2))
581 | zipAll pad1 pad2 = zipAllWith pad1 pad2 MkPair
588 | -> (this : Stream f es (List o1))
589 | -> (that : Stream f es (List o2))
590 | -> Stream f es (List o3)
591 | zipWith fun this that =
592 | zipWith_ this that (\_,_ => pure ()) (\_,_ => pure ()) (\_ => pure ()) fun
597 | (this : Stream f es (List o1))
598 | -> (that : Stream f es (List o2))
599 | -> Stream f es (List (o1,o2))
600 | zip = zipWith MkPair
604 | (this : Stream f es (List o1))
605 | -> (that : Stream f es (List o2))
606 | -> Stream f es (List o2)
607 | zipRight = Chunk.zipWith (\_ => id)
611 | (this : Stream f es (List o1))
612 | -> (that : Stream f es (List o2))
613 | -> Stream f es (List o1)
614 | zipLeft = Chunk.zipWith const