ajp*_*ajp 6 haskell haskell-pipes
说我有这个代码:
import Control.Monad.State hiding (StateT)
import Control.Proxy
server :: (Proxy p, Monad m) => Int -> Server p Int Bool (StateT Int m) ()
server = runIdentityK loop
where loop arg = do
currMax <- lift get
lift $ put $ max currMax arg
nextArg <- respond (even arg)
loop nextArg
client :: (Proxy p, Monad m) => Client p Int Bool m ()
client = runIdentityP loop
where loop = go 1
go i = do
isEven <- request i
go $ if isEven
then i `div` 2
else i * 3 + 1
Run Code Online (Sandbox Code Playgroud)
目前,客户端始终发送Int和接收Bool.但是,我希望客户端也能够查询到目前为止服务器已经看到的最高值.所以我也需要发送()和接收的通信Int.我可以将其编码为客户端发送Either Int ()和接收Either Bool Int.但是,我想确保两者没有混合 - 发送Int总是得到Bool响应.
如何才能做到这一点?
每当您希望管道具有两个单独的接口时,您必须将Proxymonad变换器嵌套在其自身中.这意味着你想要的类型:
twoInterfaces
:: (Monad m, Proxy p1, Proxy p2 )
=> () -> Int -> Server p1 Int Bool (Server p2 () Int m) r
twoInterfaces () n = runIdentityP . hoist runIdentityP $ do
x <- respond A -- Use outer interface
y <- lift $ respond B -- Use inner interface
...
Run Code Online (Sandbox Code Playgroud)
给出每个接口的以下两个客户端:
client1 :: (Monad m, Proxy p) => () -> Client p Int Bool m r
client2 :: (Monad m, Proxy p) => () -> Client p () Int m r
Run Code Online (Sandbox Code Playgroud)
您将使用以下命令将它们连接到两个服务器接口:
oneInterface () = runProxy (twoInterfaces () >-> client1)
main = runProxy (client1 >-> oneInterface)
Run Code Online (Sandbox Code Playgroud)
要了解有关此技巧的更多信息,请阅读当前教程的分支,压缩和合并部分.
你也可以反过来做.你可以拥有一个Client带有两个独立接口并连接两个不同Server的接口.这可能会或可能不会更好地适合您的问题.
请注意,这将变得更加简单pipes-4.0.0(目前在Github上),其中类型将更加简洁,您将不需要runIdentityP:
twoInterfaces
:: (Monad m) => () -> Int -> Server Int Bool (Server () Int m) r
twoInterface () n = do
x <- respond A
y <- lift $ respond B
...
client1 :: (Monad m) => () -> Client Int Bool m r
client2 :: (Monad m) => () -> Client () Int m r
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
201 次 |
| 最近记录: |