Пакет vector-0.1
имеет довольно эффективную реализацию Stream
(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
Более поздние версии vector
расширили это до монадической версии Data.Vector.Fusion.Stream.Monadic
, но для простоты воспользуемся старым, не монадическим.
Stream
вполне естественно является экземпляром Functor
и Foldable
:
instance Foldable Stream where
foldMap f s = foldl' (\a b -> a <> (f b)) mempty s
В качестве потока он также должен быть экземпляром Traversable
, не так ли? По крайней мере, на первый взгляд кажется, что это легко. Нам нужно
sequenceA :: Applicative f => Stream (f a) -> f (Stream a)
который начнется как
sequenceA (Stream step s) = Stream <$> step' <*> (pure s) where
step' = ...
<*>
— единственный способ «вытащить» аппликатив f
из-под Stream
. Теперь step'
должно быть
step' :: f (s -> Step s a)
и у нас есть в наличии
step :: s -> Step s (f a)
Все, что я знаю, это то, что f
— это Applicative
(и Functor
). Но <*>
"притягивает" f
(<*> :: f(a->b)->(f a->f b)
), а здесь мне нужно прямо противоположное, так сказать со-<*>
.
Наличие экземпляра Traversable
не имеет решающего значения ни в одном из моих начинаний, и с точки зрения производительности это может быть даже нецелесообразно. Но меня беспокоит то, что я действительно не понимаю, почему Stream
не будет Traversable
. Какой структурный элемент отсутствует, чтобы сделать Stream
Traversable
?