Reputation: 739
I've been playing with the Control.Proxy.TCP library and would like to to create a Producer from a network source.
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 ()
The code above does not type check:
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'
I see that the base monad for nsocketReadS and socketWriteD is IO while I need a different type. How can I correct this problem?
Upvotes: 2
Views: 173
Reputation: 35099
If you want to allocate a socket within a pipeline, you need to use the Control.Proxy.TCP.Safe
module, which has the alternative version of connect
that you are looking for:
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
This uses pipes-safe
to manage resource allocation within the pipeline. If you haven't used pipes-safe
before then the best place to begin is the pipes-safe tutorial.
Edit: Update to answer your question in the comment. You need to hoist
the socket reader and writer because their base monad is the surrounding proxy, not 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 ()
Upvotes: 4