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)
595 | distinctBy : (o -> o -> Bool) -> Pull f o es r -> Pull f o es r
596 | distinctBy f = catMaybes . scan Nothing next
598 | next : Maybe o -> o -> (Maybe o, Maybe o)
599 | next Nothing v = (Just v, Just v)
600 | next (Just x) v = if f x v then (Nothing,Just v) else (Just v, Just v)
605 | distinct : Eq o => Pull f o es r -> Pull f o es r
606 | distinct = distinctBy (==)
612 | scanMaybe : s -> (s -> Maybe (o -> (p,s))) -> Pull f o es r -> Pull f p es s
614 | assert_total $
case f s1 of
616 | Just g => uncons p >>= \case
618 | Right (v,p) => let (w,s2) := g v in cons w (scanMaybe s2 f p)
624 | -> (s -> o -> (Maybe p,s))
628 | scanFull s1 g last p = do
629 | assert_total $
uncons p >>= \case
630 | Left v => consMaybe (last s1) (pure v)
631 | Right (v,q) => let (w,s2) := g s1 v in consMaybe w (scanFull s2 g last q)
636 | zipWithScan : p -> (p -> o -> p) -> Pull f o es r -> Pull f (o,p) es r
637 | zipWithScan vp fun =
638 | scan vp $
\vp1,vo => let vp2 := fun vp1 vo in ((vo, vp1),vp2)
642 | zipWithScan1 : p -> (p -> o -> p) -> Pull f o es r -> Pull f (o,p) es r
643 | zipWithScan1 vp fun =
644 | scan vp $
\vp1,vo => let vp2 := fun vp1 vo in ((vo, vp2),vp2)
648 | zipWithIndex : Pull f o es r -> Pull f (o,Nat) es r
649 | zipWithIndex = zipWithScan 0 (\n,_ => S n)
653 | zipWithCount : Pull f o es r -> Pull f (o,Nat) es r
654 | zipWithCount = zipWithScan 1 (\n,_ => S n)
661 | scans : p -> (p -> o -> p) -> Pull f o es r -> Pull f p es r
662 | scans vp fun = scan vp $
\vp1,vo => let vp2 := fun vp1 vo in (vp1,vp2)
668 | scans1 : p -> (p -> o -> p) -> Pull f o es r -> Pull f p es r
670 | cons vp $
scan vp (\vp1,vo => let vp2 := fun vp1 vo in (vp2,vp2)) os
674 | scanFrom : o -> Pull f (o -> o) es r -> Pull f o es r
675 | scanFrom vo = scans vo (\x,f => f x)
679 | scanFrom1 : o -> Pull f (o -> o) es r -> Pull f o es r
680 | scanFrom1 vo = scans1 vo (\x,f => f x)
684 | runningCount : Pull f o es r -> Pull f Nat es r
685 | runningCount = scan 1 (\n,_ => (n, S n))
689 | evalScan : s -> (s -> o -> f es (p,s)) -> Pull f o es r -> Pull f p es r
691 | assert_total $
uncons p >>= \case
692 | Left res => pure res
694 | (w,s2) <- exec $
f s1 v
695 | cons w (evalScan s2 f q)
697 | parameters {0 es : List Type}
698 | {0 f : List Type -> Type -> Type}
699 | {auto func : Functor (f es)}
705 | evalScans : p -> (p -> o -> f es p) -> Pull f o es r -> Pull f p es r
707 | evalScan vp $
\vp1,vo => (\vp2 => (vp1,vp2)) <$> fun vp1 vo
711 | evalScans1 : p -> (p -> o -> f es p) -> Pull f o es r -> Pull f p es r
712 | evalScans1 vp fun =
713 | evalScan vp $
\vp1,vo => (\vp2 => (vp2,vp2)) <$> fun vp1 vo
717 | evalScanFrom : o -> Pull f (o -> f es o) es r -> Pull f o es r
718 | evalScanFrom vo = evalScans vo (\x,f => f x)
722 | evalScanFrom1 : o -> Pull f (o -> f es o) es r -> Pull f o es r
723 | evalScanFrom1 vo = evalScans1 vo (\x,f => f x)
735 | foreach : (o -> f es ()) -> Pull f o es r -> Pull f q es r
737 | assert_total $
uncons p >>= \case
739 | Right (v,p) => exec (f v) >> foreach f p
743 | foreach' : f es () -> Pull f o es r -> Pull f q es r
744 | foreach' = foreach . const
749 | observe : (o -> f es ()) -> Pull f o es r -> Pull f o es r
751 | assert_total $
uncons p >>= \case
753 | Right (v,p) => exec (act v) >> cons v (observe act p)
757 | observe' : f es () -> Pull f o es r -> Pull f o es r
758 | observe' = observe . const
764 | flatMap : Pull f o es r -> (o -> Stream f es p) -> Pull f p es r
766 | assert_total $
uncons p >>= \case
768 | Right (os,q) => g os >> flatMap q g
772 | bind : (o -> Pull f p es ()) -> Pull f o es r -> Pull f p es r
773 | bind = flip flatMap
776 | attemptOutput : Pull f o es () -> Pull f (Result es o) fs ()
778 | att (mapOutput Right p) >>= \case
779 | Left x => emit (Left x)
789 | stepLeg : Stream f es o -> Pull f p es (Maybe $
StepLeg f es o)
792 | Left _ => pure Nothing
793 | Right (v,rem) => map (Just . SL v rem) scope
797 | step : StepLeg f es o -> Pull f p es (Maybe $
StepLeg f es o)
798 | step (SL _ p sc) = inScope sc (stepLeg p)
804 | (f : List Type -> Type -> Type)
808 | ZipWithLeft f es o p = o -> Stream f es o -> Stream f es p
812 | (this : Stream f es o1)
813 | -> (that : Stream f es o2)
814 | -> (k1 : ZipWithLeft f es o1 o3)
815 | -> (k3 : Stream f es o2 -> Stream f es o3)
816 | -> (fun : o1 -> o2 -> o3)
818 | zipWith_ this that k1 k3 fun = do
819 | Just l1 <- stepLeg this | Nothing => k3 that
820 | Just l2 <- stepLeg that | Nothing => k1 l1.out l1.pull
824 | go : StepLeg f es o1 -> StepLeg f es o2 -> Stream f es o3
826 | emit (fun l1.out l2.out)
827 | Just l12 <- step l1 | Nothing => k3 l2.pull
828 | Just l22 <- step l2 | Nothing => k1 l12.out l12.pull
829 | assert_total $
go l12 l22
838 | -> (o1 -> o2 -> o3)
839 | -> (this : Stream f es o1)
840 | -> (that : Stream f es o2)
842 | zipAllWith pad1 pad2 fun this that =
843 | let kL := mapOutput (`fun` pad2)
844 | kR := mapOutput (fun pad1)
845 | k1 := \x,y => emit (fun x pad2) >> kL y
846 | in zipWith_ this that k1 kR fun
853 | -> (this : Stream f es o1)
854 | -> (that : Stream f es o2)
855 | -> Stream f es (o1,o2)
856 | zipAll pad1 pad2 = zipAllWith pad1 pad2 MkPair
863 | -> (this : Stream f es o1)
864 | -> (that : Stream f es o2)
866 | zipWith fun this that =
867 | zipWith_ this that (\_,_ => pure ()) (\_ => pure ()) fun
871 | zip : Stream f es o1 -> Stream f es o2 -> Stream f es (o1,o2)
872 | zip = zipWith MkPair
875 | zipRight : Stream f es o1 -> Stream f es o2 -> Stream f es o2
876 | zipRight = zipWith (\_ => id)
879 | zipLeft : Stream f es o1 -> Stream f es o2 -> Stream f es o1
880 | zipLeft = zipWith const
884 | hzip : All (Stream f es) ts -> Stream f es (HList ts)
886 | hzip [s] = mapOutput (::Nil) s
887 | hzip (s :: ss) = zipWith (::) s (hzip ss)
890 | 0 HZipFun : List Type -> Type -> Type
892 | HZipFun (t :: ts) r = t -> HZipFun ts r
895 | happly : HZipFun ts r -> HList ts -> r
896 | happly fun [] = fun
897 | happly fun (v :: vs) = happly (fun v) vs
902 | hzipWith : HZipFun ts r -> All (Stream f es) ts -> Stream f es r
903 | hzipWith fun = mapOutput (happly fun) . hzip