我正在为所谓的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中进行处理。
当我尝试使用Cluster
和receiveWait
来接收消息时,这一切都会破坏。
允许使用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 b
将Control.Distributed.Process.Lifted
函数提升到tansformer堆栈中,允许您使用Control.Distributed.Process
和expect
之类的函数,但不会重新映射say
,{{1等等..
我真的很想找到一个解决方法或者以match
的形式重新实现matchIf
及其朋友的方式。
任何见解都是有关的。
修改
所以在som fiddeling之后我想出了以下
match
这种方法效果相当不错,但我仍然对这种设计有多好感到好奇
答案 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
的某些中间状态?你知道,我们想知道的事实使得这种方法不仅仅是将状态存储在MVar
或distributed-process
中。
除了可疑的语义之外,如果不将distributed-process-lifted
重写为在任何地方使用MonadBaseControl
,甚至无法实现。这正是distributed-process
无法提供的原因,因为它只包含data Config = Config { clusterState :: MVar ClusterState }
的原语。
所以,我在这里要做的是传递ReaderT
环境(哦,看,Process
也这样做!)。可能IO
以明智的方式与Process
进行互动,此外,您可以轻松地将ReaderT Config Process
的任意数量的嵌套事件提升为StateT
。
重复迈克尔博客帖子的消息:IO
一般情况下都不错(在纯转换器堆栈中),仅适用于以某种方式包装AsyncTask
的情况。我鼓励你阅读这些帖子,他们对我非常鼓舞人心,所以他们又来了: