拥有类型为Producer ByteString IO ()
的生产者和类型为Pipe ByteString a IO ()
的管道,如何撰写效果,运行时会产生IO a
?
这是我最好的尝试:
{-# LANGUAGE ScopedTypeVariables #-}
import Pipes
import Data.ByteString
run :: forall a. IO a
run = runEffect $
(undefined :: Producer ByteString IO ()) >-> (undefined :: Pipe ByteString a IO ())
失败并出现以下情况:
Couldn't match type `Void' with `()'
Expected type: IO a
Actual type: IO ()
In the expression:
runEffect
$ (undefined :: Producer ByteString IO ())
>-> (undefined :: Pipe ByteString a IO ())
In an equation for `run':
run
= runEffect
$ (undefined :: Producer ByteString IO ())
>-> (undefined :: Pipe ByteString a IO ())
答案 0 :(得分:4)
通常,您需要使用Producer
撰写Consumer
才能获得Effect
runEffect
。这不是你在这里得到的,但幸运的是,有更多方法可以消除Proxy
,而不仅仅是runEffect
。
总结一下Producer
。
pipe :: Producer a IO ()
pipe = (undefined :: Producer ByteString IO ()) >-> (undefined :: Pipe ByteString a IO ())
Pipes.Prelude
模块包含许多其他消除Producers
的{{1}}的方法
Pipes.Prelude.last
获取last :: Monad m => Producer a m () -> m (Maybe a)
的最常用方法可能是使用a
Pipes.Prelude.fold
与fold :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Producer a m () -> m b
类似,但会将runEffect
缩减为其基础Producers
。既然这就是我们所拥有的,它将会很有效。以下是我们如何实施Monad
Pipes.Prelude.head
虽然值得注意slowHead = fold (\res a -> res <> First (Just a)) mempty getFirst
消耗整个slowHead
(从而执行所有需要的效果),而Producer
只执行第一个。{1}}。它太懒了!