【发布时间】:2018-07-11 04:04:58
【问题描述】:
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' = ...
<*> 是从Stream 下“拉出”应用程序f 的唯一方法。现在,step' 应该是
step' :: f (s -> Step s a)
我们有一个
step :: s -> Step s (f a)
我只知道f 是Applicative(和Functor)。但是<*> '拉入'f (<*> :: f(a->b)->(f a->f b)) 而在这里我需要完全相反的,一个co-<*> 可以这么说。
拥有Traversable 实例对我的任何努力都不是至关重要的,从性能的角度来看,它甚至可能不是可取的。但令我烦恼的是,我并没有真正理解为什么Stream 不会是Traversable。使Stream 成为Traversable 缺少什么结构元素?
【问题讨论】:
标签: haskell stream applicative traversable