转换StateT IO monad以使用Control.Proxy - 这是Server,哪个是Client?

时间:2013-06-20 06:32:02

标签: haskell haskell-pipes

我正在实施游戏引擎。我的大多数代码目前都驻留在StateT Game IO () monad中。我使用IO来获取用户输入,实际上所有IO通道都通过一个函数

getChoice :: Show a => [ a ] -> IO a

提示用户显示所有选项,读入响应并返回。对于特定的用户响应流(和初始状态),游戏确定性地进行,并且我想将这些用户响应分解出来以帮助进行测试。

当我尝试将其转换为使用管道时,最相似的是更改当前位于StateT Game IO ()的所有代码,并使其在Proxy p, Monad m => Client p [String] String m ()中运行。这样我仍然可以“请求”用户的选择,这允许我以阻塞样式编写引擎代码,假设将根据需要提供用户选择。

然而,这似乎是错误的 - 用户应该是客户端,游戏引擎是服务器吗?我可以用什么原则来正确区分这个区别?

2 个答案:

答案 0 :(得分:1)

pipes中,ServerClient几乎可以互换,上游和下游也是requestrespond。一个区别是,Client通过发出第一个请求来Session开始工作。

http://hackage.haskell.org/packages/archive/pipes/2.5.0/doc/html/Control-Proxy-Tutorial.html

我很确定你可以将游戏玩家制定为ClientServer:这完全取决于感官。为什么不把他/她当作键盘输入服务器?

答案 1 :(得分:1)

像nushio所说,ClientServer彼此完全对称。引入不对称性的唯一因素是合成运算符。 (>->)从Client结束开始,(>~>)从Server结束开始。

由于您正在使用(>->),这意味着Client组件具有“主动性”并且可以使用。这意味着除非Server生成Client,否则request将不会执行任何操作。除Client首先开始的事实外,ClientServer之间没有区别。

当您将>->Client专门化时,(Server)的类型反映了这种不对称的主动性:

(>->) => ([String] -> Server [String] String IO r)
      -> (()       -> Client [String] String IO r)
      -> (()       -> Session                IO r)

Server(即您的用户)仅对Client(即游戏引擎)作出反应,这就是服务器必须接受[String]类型的参数才能得到球的原因滚动。这反映在以下事实中:如果游戏引擎从不提示用户进行选择,则用户“永远不能运行”,因为用户没有选择的选择集。从您指定问题的方式来看,游戏引擎处于控制之中,而不是用户。如果您以相反的方式指定它并让用户驱动游戏引擎,则角色将被颠倒。