The vector-0.1
package has a quite efficient Stream
implementation (Data.Vector.Stream
):
data Step s a = Yield a s
| Skip s
| Done
-- | The type of fusible streams
data Stream a = forall s. Stream (s -> Step s a) s Size
Later versions of vector
extended this to a monadic version Data.Vector.Fusion.Stream.Monadic
, but let's use the old, un-monadic one for sake of simplicity.
Stream
is quite naturally an instance of Functor
and Foldable
:
instance Foldable Stream where
foldMap f s = foldl' (\a b -> a <> (f b)) mempty s
As a stream, it should also be an instance of Traversable
, shouldn't it? At least at first glance it looks like it's an easy one. We need a
sequenceA :: Applicative f => Stream (f a) -> f (Stream a)
which would start out as
sequenceA (Stream step s) = Stream <$> step' <*> (pure s) where
step' = ...
<*>
is the only way to 'pull out' the applicative f
from under the Stream
. Now, step'
should be
step' :: f (s -> Step s a)
and we have available a
step :: s -> Step s (f a)
All I know is that f
is an Applicative
(and Functor
). But <*>
'pulls in' the f
(<*> :: f(a->b)->(f a->f b)
) whereas here I need the exact opposite, a co-<*>
so to say.
Having a Traversable
instance isn't crucial in any of my endeavours, and from a performance point of view it might not even be advisable. But it bugs me that I don't really grasp why Stream
won't be Traversable
. What structural element is missing to make Stream
a Traversable
?