monad变换器中的分布式过程

时间:2017-09-13 07:53:52

标签: haskell monad-transformers state-monad cloud-haskell

我正在为所谓的cloud-haskell实现一个基于八卦的群集成员资格后端,或者它是Distributed.Process ..无论如何我试图在没有ioref或{{的情况下逃离handeling状态1}}而是使用状态转换器并将MVars monad放在底部,如下所示:

Process

使用type ClusterT = StateT ClusterState type Cluster a = ClusterT Process a https://hackage.haskell.org/package/distributed-process-lifted)可以很好地执行此操作:

Control.Distributed.Process.Lifted

这可以很好地工作,并且允许我很好地构建我的程序,我可以保持我的状态功能并在mystatefulcomp :: Cluster () mystatefulcomp = do msg <- expect :: Cluster String old_state <- get say $ "My old state was " ++ (show old_state) put $ modifyState curr_state msg mystatefulcomp main = do Right transport <- createTransport '127.0.0.1' '3000' (\n -> ('127.0.0.1', n) defaultTCPParameters node <- newLocalNode transport initRemoteTable runProcess node (evalStateT mystatefulcomp initialstate) where initialstate = ClusterState.empty monad中进行处理。

当我尝试使用ClusterreceiveWait来接收消息时,这一切都会破坏。

允许使用match

重写statefulcomp以执行其他操作
receiveWait

这不起作用,因为doSomethingWithString :: String -> Cluster () doSomethingWithString str = do s < get put $ modifyState s str mystatefulcomp :: Cluster () mystatefulcomp = do old_state <- get receiveWait [ match doSomthingWithString ] new_state <- get say $ "old state " ++ (show old_state) ++ " new " ++ (show new_state) 函数的类型为match,但我们希望它的类型为(a -> Process b) -> Match b。这是我在薄冰上出来的地方。我理解(a -> Cluster b) -> Match bControl.Distributed.Process.Lifted函数提升到tansformer堆栈中,允许您使用Control.Distributed.Processexpect之类的函数,但不会重新映射say,{{1等等..

我真的很想找到一个解决方法或者以match的形式重新实现matchIf及其朋友的方式。

任何见解都是有关的。

修改

所以在som fiddeling之后我想出了以下

match

这种方法效果相当不错,但我仍然对这种设计有多好感到好奇

1 个答案:

答案 0 :(得分:2)

正如Michael Snoyman指出out in a series blog(即5个链接)的posts StateT IO mystatefulcomp :: Cluster () mystatefulcomp = do old_state <- get receiveWait [ match doSomethingWithString ] new_state <- get 是个坏主意。你只是偶然发现了一个表面的实例。

new_state

问题是doSomethingWithString如果old_state抛出错误,最终会出现问题。 doSomethingWithString?在异常之前来自IORef的某些中间状态?你知道,我们想知道的事实使得这种方法不仅仅是将状态存储在MVardistributed-process中。

除了可疑的语义之外,如果不将distributed-process-lifted重写为在任何地方使用MonadBaseControl,甚至无法实现。这正是distributed-process无法提供的原因,因为它只包含data Config = Config { clusterState :: MVar ClusterState }的原语。

所以,我在这里要做的是传递ReaderT环境(哦,看,Process也这样做!)。可能IO以明智的方式与Process进行互动,此外,您可以轻松地将ReaderT Config Process的任意数量的嵌套事件提升为StateT

重复迈克尔博客帖子的消息:IO一般情况下都不错(在纯转换器堆栈中),仅适用于以某种方式包装AsyncTask的情况。我鼓励你阅读这些帖子,他们对我非常鼓舞人心,所以他们又来了:

  1. https://www.fpcomplete.com/blog/2017/06/readert-design-pattern
  2. https://www.fpcomplete.com/blog/2017/06/understanding-resourcet
  3. https://www.fpcomplete.com/blog/2017/06/tale-of-two-brackets
  4. https://www.fpcomplete.com/blog/2017/07/announcing-new-unliftio-library
  5. https://www.fpcomplete.com/blog/2017/07/the-rio-monad