我正在尝试在Haskell中实现功能性反应流。我有这个相当简单的定义:
data Observer a = Observer { next :: a -> IO () }
data Stream a = Stream { subscribe :: Observer a -> IO () }
instance Functor Stream where
fmap = mapStream
mapStream :: (a -> b) -> Stream a -> Stream b
mapStream f Stream{ subscribe=s } = Stream {
subscribe = \Observer{ next=n } -> s Observer{ next = \a -> n $ f a }
}
fromArray :: [a] -> Stream a
fromArray arr = Stream {
subscribe = \Observer{ next=n } -> forM_ arr n
}
这适用于上面的fmap
这样的简单运算符。我的问题是我如何为此实施foldStream
?我无法更改值,因此我必须使用新的种子值递归调用foldStream
。但我不知道在这种情况下如何做到这一点。我的简单定义是否可以实现这一点,还是需要不同的东西?感谢。
答案 0 :(得分:2)
foldStream
跟踪状态。你必须把这个状态放在某处,比如IORef
。
import Data.IORef
foldStream :: (a -> b -> b) -> b -> Stream a -> Stream b
foldStream f z source = Stream $ \observer -> do
ref <- newIORef z
subscribe source $ Observer $ \a -> do
b <- readIORef ref
let b' = f a b
writeIORef ref b'
next observer b'