我一直在使用 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/