Haskell Control.Proxy.TCP 生产者

标签 haskell haskell-pipes

我一直在使用 Control.Proxy.TCP 库,并希望从网络源创建一个 Producer。

producer :: Proxy p => HostName -> ServiceName -> () -> Producer p BS.ByteString IO ()
producer h p () = runIdentityP $
    lift $ connect h p $ \(s, r) ->
        runProxy $ nsocketReadS s >-> pxy >-> socketWriteD s
    where
        pxy () = runIdentityP $ do
            respond "resource-id" -- ask for "resource-id"
            bs <- request 1024    -- fetch up to 1024 bytes
            lift $ respond bs     -- and produce them from the outer proxy
            return ()

上面的代码没有进行类型检查:

Couldn't match type `p0 a'0 a1 a0 BS.ByteString m0' with `IO'
Expected type: ()
               -> ProxyFast Int BS.ByteString () BS.ByteString IO ()
  Actual type: ()
               -> ProxyFast
                    Int
                    BS.ByteString
                    ()
                    BS.ByteString
                    (p0 a'0 a1 a0 BS.ByteString m0)
                    ()
In the second argument of `(>->)', namely `pxy'
In the first argument of `(>->)', namely `nsocketReadS s >-> pxy'
In the second argument of `($)', namely
  `nsocketReadS s >-> pxy >-> socketWriteD s'

我发现 nsocketReadS 和 socketWriteD 的基本 monad 是 IO,而我需要不同的类型。我该如何解决这个问题?

最佳答案

如果要在管道内分配套接字,则需要使用 Control.Proxy.TCP.Safe 模块,该模块具有 connect 的替代版本您正在寻找:

connect
  :: (Proxy p, Monad m)
  => (forall x. SafeIO x -> m x)
  -> HostName
  -> ServiceName
  -> ((Socket, SockAddr) -> ExceptionP p a' a b' b m r)
  -> ExceptionP p a' a b' b m r

这使用pipes-safe来管理管道内的资源分配。如果您之前没有使用过 Pipes-safe,那么最好的起点是 pipes-safe tutorial .

编辑:更新以回答评论中的问题。您需要提升套接字读取器和写入器,因为它们的基本 monad 是周围的代理,而不是SafeIO

producer
    :: (Proxy p)
    => HostName -> ServiceName
    -> () -> Producer (ExceptionP p) BS.ByteString SafeIO ()
producer h p () = connect id h p $ \(s, r) ->
    runProxy $ hoist lift . nsocketReadS s >-> pxy >-> hoist lift . socketWriteD s
  where
    pxy () = do
        respond "resource-id" -- ask for "resource-id"
        bs <- request 1024    -- fetch up to 1024 bytes
        lift $ respond bs     -- and produce them from the outer proxy
        return ()

关于Haskell Control.Proxy.TCP 生产者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17259221/

相关文章:

haskell - 在 Haskell 中折叠生产者/解析器时的空间爆炸

haskell - 为什么 Haskell 管道 "use () to close unused inputs and X (the uninhabited type) to close unused outputs"?

Haskell Pipes - 获取管道中最后一个代理的返回值

haskell - 为什么这个 Haskell 模板可以工作?

haskell - 使用 haskell 项目 Euler prob 10

haskell - 如何编写一个向下游发送它从上游接收的列表的管道?

json - 使用 Pipes.Aeson 在 Haskell 中对 JSON 进行流式解析

haskell - 用于文件处理的多个异常处理程序

haskell - 尝试用 Haskell 构建词法分析程序

haskell - Aeson 的 derivedJSON 不能按预期对枚举工作