scanned currently consumes folds in a way that does not let them make use of the fact that they are always going to be applied to at least one element.
For example, attaching the maximum of all elements so far via scanned is slightly annoying. Most naturally, for s :: Stream (Of a) m r, one would use scanned like this
L.purely S.scanned L.maximum s :: Stream (Of (a, Maybe a)) m r
The Maybe here is misleading; all values are actually Just. One can rectify this via e.g. S.mapMaybe sequence, but it would be better to avoid this.
Concretely, one can generalize scanned like this:
scanned' :: Monad m => (a -> x) -> (x -> a -> x) -> (x -> b) -> Stream (Of a) m r -> Stream (Of (a, b)) m r
scanned' begin step done = loop Nothing
where
loop m stream =
case stream of
Return r -> return r
Effect mn -> Effect $ fmap (loop m) mn
Step (a :> rest) ->
case m of
Nothing -> do
let !x = begin a
!b = done x
S.yield (a, b)
loop (Just x) rest
Just x -> do
let !x' = step x a
!b = done x'
S.yield (a, b)
loop (Just x') rest
One can easily define scanned in terms of scanned', namely
scanned step begin done = scanned' (const begin) step done
In the example above, one can now write
L1.purely scanned' L1.maximum :: Stream (Of (a, a)) m r
using import qualified Control.Foldl.NonEmpty as L1.
scannedcurrently consumes folds in a way that does not let them make use of the fact that they are always going to be applied to at least one element.For example, attaching the maximum of all elements so far via
scannedis slightly annoying. Most naturally, fors :: Stream (Of a) m r, one would usescannedlike thisThe
Maybehere is misleading; all values are actuallyJust. One can rectify this via e.g.S.mapMaybe sequence, but it would be better to avoid this.Concretely, one can generalize
scannedlike this:One can easily define
scannedin terms ofscanned', namelyIn the example above, one can now write
using
import qualified Control.Foldl.NonEmpty as L1.