data Step s a = Done | Skip !s | Yield !a !s
fmap _ Done = Done
fmap _ (Skip s) = Skip s
fmap f (Yield a s) = Yield (f a) s
bimap _ _ Done = Done
bimap f _ (Skip s) = Skip (f s)
bimap f g (Yield a s) = Yield (g a) (f s)
Nothing
stepState (Skip st) = Just st
stepState (Yield _ st) = Just st
newtype StepFun s a = StepFun (s -> Step s a)
fmap f inif = inif >>= (\x -> pure (f x))
pure x = StepFun $ \st -> Yield x st
f <*> v = f >>= (\fx -> v >>= (\vx -> StepFun $ Yield (fx vx)))
return = pure
(StepFun f1) >>= f2 = StepFun go
where
go st = case f1 st of
Done -> Done
Skip st2 -> Skip st2
Yield x st2 -> let (StepFun f3) = (f2 x) in f3 st2
-- this makes `guard` work
empty = StepFun $ Skip
StepFun f1 <|> StepFun f2 = StepFun $ \st ->
case f1 st of
Yield a st2 -> Yield a st2
-- backtracking
Done -> f2 st
Skip _ -> f2 st
data Stream a = forall s. Stream
(StepFun s a) -- ^ stepper function
!s -- ^ current state
fmap f (Stream step_ cst) = Stream (fmap f step_) cst
go ctx
where
go st = case sf st of
Done -> []
Skip st2 -> go st2
Yield a st2 -> a:(go st2)
-- | convert a list to a stream
Stream (StepFun go)
where
go [] = Done
go (x:xs) = Yield x xs
Done
smap (TF.Skip st) = Skip st
smap (TF.Yield av st) = Yield av st
-- | embed a stream from Data.Text into our stream type
Stream (StepFun (smap . step_)) st
-- | step an inner stream;
-- forwards skips and turns Done into Nothing-yields
StepFun $ \(Stream (StepFun f) st) -> case f st of
Done -> Yield Nothing (Stream (StepFun f) st)
Skip st2 -> Skip (Stream (StepFun f) st2)
Yield x st2 -> Yield (Just x) (Stream (StepFun f) st2)