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 | parameters {auto sca : Scan t}
374 | scan : s -> (s -> o -> (p,s)) -> Pull f (t o) es r -> Pull f (t p) es r
375 | scan ini f = P.scan ini (scanChunk f)
381 | zipWithScan : p -> (p -> o -> p) -> Pull f (t o) es r -> Pull f (t (o,p)) es r
382 | zipWithScan vp fun =
383 | Chunk.scan vp $
\vp1,vo => let vp2 := fun vp1 vo in ((vo, vp1),vp2)
387 | zipWithScan1 : p -> (p -> o -> p) -> Pull f (t o) es r -> Pull f (t (o,p)) es r
388 | zipWithScan1 vp fun =
389 | Chunk.scan vp $
\vp1,vo => let vp2 := fun vp1 vo in ((vo, vp2),vp2)
393 | zipWithIndex : Pull f (t o) es r -> Pull f (t (o,Nat)) es r
394 | zipWithIndex = Chunk.zipWithScan 0 (\n,_ => S n)
398 | zipWithCount : Pull f (t o) es r -> Pull f (t (o,Nat)) es r
399 | zipWithCount = Chunk.zipWithScan 1 (\n,_ => S n)
403 | runningCount : Pull f (t o) es r -> Pull f (t Nat) es r
404 | runningCount = Chunk.scan 1 (\n,_ => (n, S n))
411 | len : SnocList a -> Maybe (List a)
412 | len = nel . (<>> [])
414 | broken : SnocList a -> List a -> BreakRes (List a)
415 | broken sx xs = Broken (len sx) (nel xs)
420 | -> (s -> Either r (o,s))
422 | -> UnfoldRes r s (List o)
423 | unfoldList sx 0 f x = More (sx <>> []) x
424 | unfoldList sx (S k) f x =
426 | Right (v,x2) => unfoldList (sx:<v) k f x2
427 | Left res => Last res (sx <>> [])
429 | splitAtList : SnocList o -> Nat -> List o -> SplitRes (List o)
430 | splitAtList sx (S k) (h::t) = splitAtList (sx :< h) k t
431 | splitAtList sx n [] = All n
432 | splitAtList sx 0 xs = Middle (sx <>> []) xs
436 | -> BreakInstruction
439 | -> BreakRes (List a)
440 | breakList sx b f [] = Keep (sx <>> [])
441 | breakList sx b f (x :: xs) =
444 | TakeHit => broken (sx :< x) xs
445 | PostHit => broken sx (x::xs)
446 | DropHit => broken sx xs
447 | False => breakList (sx :< x) b f xs
450 | Chunk (List a) a where
451 | unfoldChunk @{CS (S n)} f x =
453 | Left res => Done res
454 | Right (v,x2) => unfoldList [<v] n f x2
456 | replicateChunk @{CS n} = List.replicate n
461 | unconsChunk [] = Nothing
462 | unconsChunk (h::t) = Just (h, nel t)
464 | splitChunkAt = splitAtList [<]
466 | breakChunk = breakList [<]
468 | filterChunk pred = nel . filter pred
470 | scanListImpl : SnocList p -> (s -> o -> (p,s)) -> s -> List o -> (List p,s)
471 | scanListImpl sx f v [] = (sx <>> [], v)
472 | scanListImpl sx f v (x :: xs) =
473 | let (vp,v2) := f v x
474 | in scanListImpl (sx :< vp) f v2 xs
478 | scanChunk = scanListImpl [<]
485 | data ZipRes : (a,b,c : Type) -> Type where
486 | ZB : List c -> ZipRes a b c
487 | ZL : List a -> List c -> ZipRes a b c
488 | ZR : List b -> List c -> ZipRes a b c
490 | zipImpl : SnocList c -> (a -> b -> c) -> List a -> List b -> ZipRes a b c
491 | zipImpl sx f (x::xs) (y::ys) = zipImpl (sx :< f x y) f xs ys
492 | zipImpl sx f [] [] = ZB (sx <>> [])
493 | zipImpl sx f xs [] = ZL xs (sx <>> [])
494 | zipImpl sx f [] ys = ZR ys (sx <>> [])
497 | (this : Stream f es (List o1))
498 | -> (that : Stream f es (List o2))
499 | -> (k1 : ZipWithLeft f es (List o1) (List o3))
500 | -> (k2 : ZipWithLeft f es (List o2) (List o3))
501 | -> (k3 : Stream f es (List o2) -> Stream f es (List o3))
502 | -> (fun : o1 -> o2 -> o3)
503 | -> Stream f es (List o3)
504 | zipWith_ this that k1 k2 k3 fun = do
505 | Just l1 <- stepLeg this | Nothing => k3 that
506 | Just l2 <- stepLeg that | Nothing => k1 l1.out l1.pull
510 | go : StepLeg f es (List o1) -> StepLeg f es (List o2) -> Stream f es (List o3)
512 | case zipImpl [<] fun l1.out l2.out of
515 | Just l12 <- step l1 | Nothing => k3 l2.pull
516 | Just l22 <- step l2 | Nothing => k1 l12.out l12.pull
517 | assert_total $
go l12 l22
520 | Just l22 <- step l2 | Nothing => k1 as l1.pull
521 | assert_total $
go ({out := as} l1) l22
524 | Just l12 <- step l1 | Nothing => k2 bs l2.pull
525 | assert_total $
go l12 ({out := bs} l2)
534 | -> (o1 -> o2 -> o3)
535 | -> (this : Stream f es (List o1))
536 | -> (that : Stream f es (List o2))
537 | -> Stream f es (List o3)
538 | zipAllWith pad1 pad2 fun this that =
539 | let kL := Chunk.mapOutput (`fun` pad2)
540 | kR := Chunk.mapOutput (fun pad1)
541 | k1 := \x,y => emit (map (`fun` pad2) x) >> kL y
542 | k2 := \x,y => emit (map (fun pad1) x) >> kR y
543 | in zipWith_ this that k1 k2 kR fun
550 | -> (this : Stream f es (List o1))
551 | -> (that : Stream f es (List o2))
552 | -> Stream f es (List (o1,o2))
553 | zipAll pad1 pad2 = zipAllWith pad1 pad2 MkPair
560 | -> (this : Stream f es (List o1))
561 | -> (that : Stream f es (List o2))
562 | -> Stream f es (List o3)
563 | zipWith fun this that =
564 | zipWith_ this that (\_,_ => pure ()) (\_,_ => pure ()) (\_ => pure ()) fun
569 | (this : Stream f es (List o1))
570 | -> (that : Stream f es (List o2))
571 | -> Stream f es (List (o1,o2))
572 | zip = zipWith MkPair
576 | (this : Stream f es (List o1))
577 | -> (that : Stream f es (List o2))
578 | -> Stream f es (List o2)
579 | zipRight = Chunk.zipWith (\_ => id)
583 | (this : Stream f es (List o1))
584 | -> (that : Stream f es (List o2))
585 | -> Stream f es (List o1)
586 | zipLeft = Chunk.zipWith const