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?