我正在尝试通过编写自己的
我很难接受这个函数如何能够继续接收值,只要有值可用,然后以某种方式将该总和返回给用户。我猜类型会是:
然而,在
sum
函数来学习pipes
包,但我遇到了困难。我不想使用来自Pipes.Prelude
的实用函数(因为它具有sum
和fold
等使其变得微不足道的其他函数),而只使用Pipes.Tutorial
中描述的信息。教程没有讨论Proxy
的构造函数,但如果我查看sum
和fold
的源代码,它们使用这些构造函数,我想知道是否可能在不了解这些低级细节的情况下编写我的sum
函数。我很难接受这个函数如何能够继续接收值,只要有值可用,然后以某种方式将该总和返回给用户。我猜类型会是:
sum' :: Monad m => Consumer Int m Int
我认为这可能行得通,因为这个函数可以消耗值直到没有更多的值可用,然后返回最终总和。我会像这样使用它:
mysum <- runEffect $ inputs >-> sum'
然而,在
Pipes.Prelude
中的该函数实际上有以下签名:sum :: (Monad m, Num a) => Producer a m () -> m a
所以我想这是我的第一个障碍。为什么sum
函数接受一个Producer
作为参数,而不是使用>->
进行连接?
顺便说一下,在danidiaz的答案后,我最终得到了以下结果:
sum' = go 0
where
go n p = next p >>= \x -> case x of
Left _ -> return n
Right (_, p') -> go (n + 1) p'
sum
接受一个生成数字并在单子操作中将它们相加的东西...如果你仔细想想,这个想法与你的想法非常相似 - 此外,该软件包的设计使您不必关心细节,而是使用fold
和提供的其他基元 ;) - Random Dev