9 | import Control.Monad.MCancel
10 | import Control.Monad.Resource
13 | import Data.List.Quantifiers
14 | import public FS.Core
16 | import Data.SnocList
19 | %hide Data.Linear.(.)
26 | data UnfoldRes : (r,s,o : Type) -> Type where
27 | More : (vals : o) -> (st : s) -> UnfoldRes r s o
28 | Done : (res : r) -> UnfoldRes r s o
29 | Last : (res : r) -> (vals : o) -> UnfoldRes r s o
33 | emits : List o -> Stream f es o
35 | emits (h::t) = cons h (emits t)
39 | emitList : List o -> Stream f es (List o)
40 | emitList [] = pure ()
41 | emitList vs = emit vs
45 | emitMaybe : Maybe o -> Stream f es o
46 | emitMaybe Nothing = pure ()
47 | emitMaybe (Just v) = emit v
51 | emitSnoc : SnocList o -> Maybe o -> Stream f es (List o)
52 | emitSnoc sv m = emitList $
(sv <>> maybe [] pure m)
57 | eval : f es o -> Stream f es o
58 | eval act = exec act >>= emit
68 | unfold : (init : s) -> (s -> UnfoldRes r s o) -> Pull f o es r
71 | More vals st => cons vals (unfold st g)
72 | Done res => pure res
73 | Last res vals => cons vals (pure res)
78 | unfoldEval : (init : s) -> (s -> f es (UnfoldRes r s o)) -> Pull f o es r
79 | unfoldEval cur act =
80 | assert_total $
exec (act cur) >>= \case
81 | More vals st => cons vals (unfoldEval st act)
82 | Done res => pure res
83 | Last res vals => cons vals (pure res)
88 | unfoldEvalMaybe : f es (Maybe o) -> Stream f es o
89 | unfoldEvalMaybe act =
90 | assert_total $
exec act >>= \case
92 | Just o => cons o (unfoldEvalMaybe act)
96 | fill : o -> Pull f o es ()
97 | fill v = cons v (fill v)
103 | iterate : o -> (o -> o) -> Pull f o es ()
104 | iterate v f = unfold v (\x => More x $
f x)
108 | replicate : Nat -> o -> Stream f es o
109 | replicate 0 _ = pure ()
110 | replicate (S k) v = cons v (replicate k v)
114 | repeat : Stream f es o -> Pull f o es ()
115 | repeat v = assert_total $
v >> repeat v
119 | consMaybe : Maybe o -> Pull f o es r -> Pull f o es r
120 | consMaybe (Just v) p = cons v p
121 | consMaybe Nothing p = p
123 | 0 cproof : NonEmpty (as ++ [a])
124 | cproof {as = []} = %search
125 | cproof {as = _::_} = %search
130 | cycle : (as : List a) -> (0 p : NonEmpty as) => Stream f es a
131 | cycle (v::vs) = assert_total $
emit v >> cycle (vs ++ [v]) @{cproof}
138 | data BreakInstruction : Type where
140 | TakeHit : BreakInstruction
143 | PostHit : BreakInstruction
146 | DropHit : BreakInstruction
150 | peek : Pull f o es r -> Pull f q es (Either r (o, Pull f o es r))
154 | Right (vs,q) => Right (vs, cons vs q)
158 | peekRes : Pull f o es r -> Pull f q es (Either r (Pull f o es r))
159 | peekRes = map (map snd) . peek
163 | drain : Pull f o es r -> Pull f q es r
165 | assert_total $
uncons p >>= \case
167 | Right (_,p) => drain p
175 | splitAt : Nat -> Pull f o es r -> Pull f o es (Pull f o es r)
176 | splitAt 0 p = pure p
178 | assert_total $
uncons p >>= \case
179 | Left v => pure (pure v)
180 | Right (v,q) => cons v (splitAt k q)
184 | take : Nat -> Pull f o es r -> Stream f es o
185 | take n = ignore . newScope . splitAt n
195 | limit : Has e es => Lazy e -> Nat -> Pull f o es r -> Pull f o es r
198 | Left v <- peekRes q | Right _ => throw err
204 | drop : Nat -> Pull f o es r -> Pull f o es r
205 | drop k q = join $
drain (splitAt k q)
209 | head : Pull f o es r -> Stream f es o
214 | tail : Pull f o es r -> Pull f o es r
220 | data BreakRes : (c : Type) -> Type where
222 | Broken : (pre, post : Maybe c) -> BreakRes c
224 | Keep : c -> BreakRes c
231 | (orElse : r -> Pull f o es r)
232 | -> (o -> BreakRes o)
234 | -> Pull f o es (Pull f o es r)
235 | breakPull orElse g p =
236 | assert_total $
uncons p >>= \case
237 | Left r => pure (orElse r)
238 | Right (v,q) => case g v of
239 | Keep w => cons w (breakPull orElse g q)
240 | Broken pre pst => consMaybe pre (pure $
consMaybe pst q)
249 | (orElse : r -> Pull f o es r)
250 | -> BreakInstruction
253 | -> Pull f o es (Pull f o es r)
254 | breakFull orElse bi pred =
255 | breakPull orElse $
\v => case pred v of
258 | TakeHit => Broken (Just v) Nothing
259 | PostHit => Broken Nothing (Just v)
260 | DropHit => Broken Nothing Nothing
266 | {auto has : Has e es}
268 | -> BreakInstruction
271 | -> Pull f o es (Pull f o es r)
272 | forceBreakFull err = breakFull (const $
throw err)
279 | takeUntil : BreakInstruction -> (o -> Bool) -> Pull f o es r -> Stream f es o
280 | takeUntil tf pred = ignore . newScope . breakFull pure tf pred
285 | takeWhile : (o -> Bool) -> Pull f o es r -> Stream f es o
286 | takeWhile pred = takeUntil DropHit (not . pred)
290 | takeThrough : (o -> Bool) -> Pull f o es r -> Stream f es o
291 | takeThrough pred = takeUntil TakeHit (not . pred)
295 | takeWhileJust : Pull f (Maybe o) es r -> Stream f es o
296 | takeWhileJust = newScope . go
298 | go : Pull f (Maybe o) es r -> Stream f es o
300 | assert_total $
uncons p >>= \case
302 | Right (Just v,q) => cons v (takeWhileJust q)
303 | Right (Nothing,q) => pure ()
310 | dropUntil : BreakInstruction -> (o -> Bool) -> Pull f o es r -> Pull f o es r
311 | dropUntil tf pred p = drain (breakFull pure tf pred p) >>= id
316 | dropWhile : (o -> Bool) -> Pull f o es r -> Pull f o es r
317 | dropWhile pred = dropUntil PostHit (not . pred)
322 | dropThrough : (o -> Bool) -> Pull f o es r -> Pull f o es r
323 | dropThrough pred = dropUntil DropHit (not . pred)
331 | mapMaybe : (o -> Maybe p) -> Pull f o es r -> Pull f p es r
333 | assert_total $
uncons p >>= \case
335 | Right (v,q) => case f v of
336 | Just w => cons w (mapMaybe f q)
337 | Nothing => mapMaybe f q
341 | catMaybes : Pull f (Maybe o) es r -> Pull f o es r
342 | catMaybes = mapMaybe id
346 | mapRight : (o -> Either e p) -> Pull f o es r -> Pull f p es r
347 | mapRight f = mapMaybe (getRight . f)
351 | catRights : Pull f (Either e o) es r -> Pull f o es r
352 | catRights = mapMaybe getRight
356 | mapLeft : (o -> Either e p) -> Pull f o es r -> Pull f e es r
357 | mapLeft f = mapMaybe (getLeft . f)
361 | catLefts : Pull f (Either e o) es r -> Pull f e es r
362 | catLefts = mapMaybe getLeft
366 | mapOutput : (o -> p) -> Pull f o es r -> Pull f p es r
367 | mapOutput f = mapMaybe (Just . f)
371 | evalMap : (o -> f es p) -> Pull f o es r -> Pull f p es r
373 | assert_total $
uncons p >>= \case
377 | cons ws (evalMap f p)
381 | evalMapMaybe : (o -> f es (Maybe p)) -> Pull f o es r -> Pull f p es r
383 | assert_total $
uncons p >>= \case
386 | Just w <- exec (f v) | Nothing => evalMapMaybe f q
387 | cons w (evalMapMaybe f q)
392 | filter : (o -> Bool) -> Pull f o es r -> Pull f o es r
394 | assert_total $
uncons p >>= \case
396 | Right (v,q) => case pred v of
397 | True => cons v (filter pred q)
398 | False => filter pred q
402 | filterNot : (o -> Bool) -> Pull f o es r -> Pull f o es r
403 | filterNot pred = filter (not . pred)
408 | endWithNothing : Pull f o es r -> Pull f (Maybe o) es r
409 | endWithNothing s = mapOutput Just s >>= \res => cons Nothing (pure res)
420 | pairLastOr : Lazy o -> Pull f o es r -> Pull f p es (o,r)
421 | pairLastOr dflt s =
422 | assert_total $
uncons s >>= \case
423 | Left res => pure (dflt,res)
424 | Right (v,q) => pairLastOr v q
429 | lastOr : Lazy o -> Stream f es o -> Pull f p es o
430 | lastOr dflt s = fst <$> pairLastOr dflt s
435 | pairLastOrErr : Has e es => Lazy e -> Pull f o es r -> Pull f p es (o,r)
436 | pairLastOrErr err s =
438 | Left res => throw err
439 | Right (v,q) => pairLastOr v q
444 | lastOrErr : Has e es => Lazy e -> Stream f es o -> Pull f p es o
445 | lastOrErr err s = fst <$> pairLastOrErr err s
451 | fold : (p -> o -> p) -> p -> Pull f o es r -> Pull f p es r
453 | assert_total $
uncons s >>= \case
454 | Left res => cons v (pure res)
455 | Right (vs,s2) => fold g (g v vs) s2
460 | foldPair : (p -> o -> p) -> p -> Pull f o es r -> Pull f q es (p,r)
462 | assert_total $
uncons s >>= \case
463 | Left res => pure (v, res)
464 | Right (vs,s2) => foldPair g (g v vs) s2
469 | {auto has : Has e es}
470 | -> (p -> o -> Either e p)
473 | -> Pull f q es (p,r)
475 | assert_total $
uncons s >>= \case
476 | Left res => pure (v, res)
477 | Right (vs,s2) => case g v vs of
478 | Right v2 => foldPairE g v2 s2
483 | foldGet : (p -> o -> p) -> p -> Stream f es o -> Pull f q es p
484 | foldGet acc ini = map fst . foldPair acc ini
488 | fold1 : (o -> o -> o) -> Pull f o es r -> Pull f o es r
492 | Right (v,q) => fold g v q
497 | all : (o -> Bool) -> Pull f o es r -> Stream f es Bool
499 | assert_total $
uncons p >>= \case
500 | Left _ => emit True
501 | Right (vs,q) => case pred vs of
503 | False => emit False
508 | any : (o -> Bool) -> Pull f o es r -> Stream f es Bool
510 | assert_total $
uncons p >>= \case
511 | Left _ => emit False
512 | Right (vs,q) => case pred vs of
513 | False => any pred q
518 | sum : Num o => Pull f o es r -> Pull f o es r
523 | count : Pull f o es r -> Pull f Nat es r
524 | count = fold (const . S) 0
528 | maximum : Ord o => Pull f o es r -> Pull f o es r
529 | maximum = fold1 max
533 | minimum : Ord o => Pull f o es r -> Pull f o es r
534 | minimum = fold1 min
538 | mappend : Semigroup o => Pull f o es r -> Pull f o es r
539 | mappend = fold1 (<+>)
547 | foldMap : Monoid m => (o -> m) -> Pull f o es r -> Pull f m es r
548 | foldMap f = fold (\v,el => v <+> f el) neutral
554 | evalFold : (p -> o -> f es p) -> p -> Pull f o es r -> Pull f p es r
556 | assert_total $
uncons s >>= \case
557 | Left res => cons v (pure res)
558 | Right (vs,s2) => exec (g v vs) >>= \v2 => evalFold g v2 s2
563 | evalFoldPair : (p -> o -> f es p) -> p -> Pull f o es r -> Pull f q es (p,r)
564 | evalFoldPair g v s =
565 | assert_total $
uncons s >>= \case
566 | Left res => pure (v, res)
567 | Right (vs,s2) => exec (g v vs) >>= \v2 => evalFoldPair g v2 s2
571 | evalFoldGet : (p -> o -> f es p) -> p -> Stream f es o -> Pull f q es p
572 | evalFoldGet acc ini = map fst . evalFoldPair acc ini
580 | scan : s -> (s -> o -> (p,s)) -> Pull f o es r -> Pull f p es r
582 | assert_total $
uncons p >>= \case
583 | Left res => pure res
584 | Right (v,q) => let (w,s2) := f s1 v in cons w (scan s2 f q)
588 | scanReturn : s -> (s -> o -> (p,s)) -> Stream f es o -> Pull f p es s
589 | scanReturn s1 f p =
590 | assert_total $
uncons p >>= \case
592 | Right (v,q) => let (w,s2) := f s1 v in cons w (scanReturn s2 f q)
596 | escanReturn : s -> (s -> o -> Result es (p,s)) -> Stream f es o -> Pull f p es s
597 | escanReturn s1 f p =
598 | assert_total $
uncons p >>= \case
601 | let Right (w,s2) := f s1 v | Left x => fail x
602 | in cons w (escanReturn s2 f q)
613 | distinctBy : (o -> o -> Bool) -> Pull f o es r -> Pull f o es r
614 | distinctBy f = catMaybes . scan Nothing next
616 | next : Maybe o -> o -> (Maybe o, Maybe o)
617 | next Nothing v = (Just v, Just v)
618 | next (Just x) v = if f x v then (Nothing,Just v) else (Just v, Just v)
623 | distinct : Eq o => Pull f o es r -> Pull f o es r
624 | distinct = distinctBy (==)
630 | scanMaybe : s -> (s -> Maybe (o -> (p,s))) -> Pull f o es r -> Pull f p es s
632 | assert_total $
case f s1 of
634 | Just g => uncons p >>= \case
636 | Right (v,p) => let (w,s2) := g v in cons w (scanMaybe s2 f p)
642 | -> (s -> o -> (Maybe p,s))
646 | scanFull s1 g last p = do
647 | assert_total $
uncons p >>= \case
648 | Left v => consMaybe (last s1) (pure v)
649 | Right (v,q) => let (w,s2) := g s1 v in consMaybe w (scanFull s2 g last q)
654 | zipWithScan : p -> (p -> o -> p) -> Pull f o es r -> Pull f (o,p) es r
655 | zipWithScan vp fun =
656 | scan vp $
\vp1,vo => let vp2 := fun vp1 vo in ((vo, vp1),vp2)
660 | zipWithScan1 : p -> (p -> o -> p) -> Pull f o es r -> Pull f (o,p) es r
661 | zipWithScan1 vp fun =
662 | scan vp $
\vp1,vo => let vp2 := fun vp1 vo in ((vo, vp2),vp2)
666 | zipWithIndex : Pull f o es r -> Pull f (o,Nat) es r
667 | zipWithIndex = zipWithScan 0 (\n,_ => S n)
671 | zipWithCount : Pull f o es r -> Pull f (o,Nat) es r
672 | zipWithCount = zipWithScan 1 (\n,_ => S n)
679 | scans : p -> (p -> o -> p) -> Pull f o es r -> Pull f p es r
680 | scans vp fun = scan vp $
\vp1,vo => let vp2 := fun vp1 vo in (vp1,vp2)
686 | scans1 : p -> (p -> o -> p) -> Pull f o es r -> Pull f p es r
688 | cons vp $
scan vp (\vp1,vo => let vp2 := fun vp1 vo in (vp2,vp2)) os
692 | scanFrom : o -> Pull f (o -> o) es r -> Pull f o es r
693 | scanFrom vo = scans vo (\x,f => f x)
697 | scanFrom1 : o -> Pull f (o -> o) es r -> Pull f o es r
698 | scanFrom1 vo = scans1 vo (\x,f => f x)
702 | runningCount : Pull f o es r -> Pull f Nat es r
703 | runningCount = scan 1 (\n,_ => (n, S n))
707 | evalScan : s -> (s -> o -> f es (p,s)) -> Pull f o es r -> Pull f p es r
709 | assert_total $
uncons p >>= \case
710 | Left res => pure res
712 | (w,s2) <- exec $
f s1 v
713 | cons w (evalScan s2 f q)
715 | parameters {0 es : List Type}
716 | {0 f : List Type -> Type -> Type}
717 | {auto func : Functor (f es)}
723 | evalScans : p -> (p -> o -> f es p) -> Pull f o es r -> Pull f p es r
725 | evalScan vp $
\vp1,vo => (\vp2 => (vp1,vp2)) <$> fun vp1 vo
729 | evalScans1 : p -> (p -> o -> f es p) -> Pull f o es r -> Pull f p es r
730 | evalScans1 vp fun =
731 | evalScan vp $
\vp1,vo => (\vp2 => (vp2,vp2)) <$> fun vp1 vo
735 | evalScanFrom : o -> Pull f (o -> f es o) es r -> Pull f o es r
736 | evalScanFrom vo = evalScans vo (\x,f => f x)
740 | evalScanFrom1 : o -> Pull f (o -> f es o) es r -> Pull f o es r
741 | evalScanFrom1 vo = evalScans1 vo (\x,f => f x)
753 | foreach : (o -> f es ()) -> Pull f o es r -> Pull f q es r
755 | assert_total $
uncons p >>= \case
757 | Right (v,p) => exec (f v) >> foreach f p
761 | foreach' : f es () -> Pull f o es r -> Pull f q es r
762 | foreach' = foreach . const
767 | observe : (o -> f es ()) -> Pull f o es r -> Pull f o es r
769 | assert_total $
uncons p >>= \case
771 | Right (v,p) => exec (act v) >> cons v (observe act p)
775 | observe' : f es () -> Pull f o es r -> Pull f o es r
776 | observe' = observe . const
782 | flatMap : Pull f o es r -> (o -> Stream f es p) -> Pull f p es r
784 | assert_total $
uncons p >>= \case
786 | Right (os,q) => g os >> flatMap q g
790 | bind : (o -> Pull f p es ()) -> Pull f o es r -> Pull f p es r
791 | bind = flip flatMap
794 | attemptOutput : Pull f o es () -> Pull f (Result es o) fs ()
796 | att (mapOutput Right p) >>= \case
797 | Left x => emit (Left x)
807 | stepLeg : Stream f es o -> Pull f p es (Maybe $
StepLeg f es o)
810 | Left _ => pure Nothing
811 | Right (v,rem) => map (Just . SL v rem) scope
815 | step : StepLeg f es o -> Pull f p es (Maybe $
StepLeg f es o)
816 | step (SL _ p sc) = inScope sc (stepLeg p)
822 | (f : List Type -> Type -> Type)
826 | ZipWithLeft f es o p = o -> Stream f es o -> Stream f es p
830 | (this : Stream f es o1)
831 | -> (that : Stream f es o2)
832 | -> (k1 : ZipWithLeft f es o1 o3)
833 | -> (k3 : Stream f es o2 -> Stream f es o3)
834 | -> (fun : o1 -> o2 -> o3)
836 | zipWith_ this that k1 k3 fun = do
837 | Just l1 <- stepLeg this | Nothing => k3 that
838 | Just l2 <- stepLeg that | Nothing => k1 l1.out l1.pull
842 | go : StepLeg f es o1 -> StepLeg f es o2 -> Stream f es o3
844 | emit (fun l1.out l2.out)
845 | Just l12 <- step l1 | Nothing => k3 l2.pull
846 | Just l22 <- step l2 | Nothing => k1 l12.out l12.pull
847 | assert_total $
go l12 l22
856 | -> (o1 -> o2 -> o3)
857 | -> (this : Stream f es o1)
858 | -> (that : Stream f es o2)
860 | zipAllWith pad1 pad2 fun this that =
861 | let kL := mapOutput (`fun` pad2)
862 | kR := mapOutput (fun pad1)
863 | k1 := \x,y => emit (fun x pad2) >> kL y
864 | in zipWith_ this that k1 kR fun
871 | -> (this : Stream f es o1)
872 | -> (that : Stream f es o2)
873 | -> Stream f es (o1,o2)
874 | zipAll pad1 pad2 = zipAllWith pad1 pad2 MkPair
881 | -> (this : Stream f es o1)
882 | -> (that : Stream f es o2)
884 | zipWith fun this that =
885 | zipWith_ this that (\_,_ => pure ()) (\_ => pure ()) fun
889 | zip : Stream f es o1 -> Stream f es o2 -> Stream f es (o1,o2)
890 | zip = zipWith MkPair
893 | zipRight : Stream f es o1 -> Stream f es o2 -> Stream f es o2
894 | zipRight = zipWith (\_ => id)
897 | zipLeft : Stream f es o1 -> Stream f es o2 -> Stream f es o1
898 | zipLeft = zipWith const
902 | hzip : All (Stream f es) ts -> Stream f es (HList ts)
904 | hzip [s] = mapOutput (::Nil) s
905 | hzip (s :: ss) = zipWith (::) s (hzip ss)
908 | 0 HZipFun : List Type -> Type -> Type
910 | HZipFun (t :: ts) r = t -> HZipFun ts r
913 | happly : HZipFun ts r -> HList ts -> r
914 | happly fun [] = fun
915 | happly fun (v :: vs) = happly (fun v) vs
920 | hzipWith : HZipFun ts r -> All (Stream f es) ts -> Stream f es r
921 | hzipWith fun = mapOutput (happly fun) . hzip