代码之家  ›  专栏  ›  技术社区  ›  Patrik

monad transformer中的分布式过程

  •  1
  • Patrik  · 技术社区  · 7 年前

    我在考虑为所谓的 cloud-haskell Distributed.Process .. 不管怎么说,我试图摆脱没有人干预的状态 ioref MVars 相反,使用状态转换器并将 Process 单子在底部,像这样:

    type ClusterT = StateT ClusterState
    type Cluster a = ClusterT Process a
    

    这在使用 Control.Distributed.Process.Lifted ( https://hackage.haskell.org/package/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
    

    这可以很好地工作,允许我很好地构造程序,我可以保持我的状态功能并在 Cluster 单子。

    receiveWait match 接收消息。

    让我们重写 statefulcomp 接收等待

    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)
    

    自从 (a -> Process b) -> Match b 但我们希望它是一种 (a -> Cluster b) -> Match b . 这就是我在薄冰上下车的地方。据我所知 控制分布式。过程举起 rexposes公司 Control.Distributed.Process expect say 火柴 matchIf

    我真的为此苦苦挣扎,试图找到一个解决办法或重新实施的方法 火柴 MonadProcess m => (a -> m b) -> Match b .

    任何见解都是必要的。

    编辑

    因此,在经历了一些烦躁之后,我提出了以下建议

    doSomethingWithString :: String -> Cluster ()
    doSomethingWithString str = do
       s < get
       put $ modifyState s str
    
    doSomethingWithInt :: Int -> Cluster ()
    ...
    
    mystatefulcomp :: Cluster ()
    mystatefulcomp = do
       old_state <- get
       id =<< receiveWait [ match $ return . doSomethingWithString
                          , match $ return . doSomethingWithInt ]
       new_state <- get
       say $ "old state " ++ (show old_state) ++ " new " ++ (show new_state)
    

    1 回复  |  直到 7 年前
        1
  •  2
  •   Sebastian Graf    7 年前

    正如迈克尔·斯诺曼指出的那样 out in a series 属于 blog posts StateT IO 这是个坏主意。你刚刚偶然发现了一个例子。

    mystatefulcomp :: Cluster ()
    mystatefulcomp = do
       old_state <- get
       receiveWait [ match doSomethingWithString ]
       new_state <- get
    

    问题是最终结果是什么 new_state doSomethingWithString 抛出错误。这个 old_state ? 一些中间状态来自 在异常之前?你看,正是我们想知道的事实使得这种方法不亚于将状态存储在 IORef MVar .

    distributed-process 正在重写以使用 MonadBaseControl distributed-process-lifted 未能交付,因为它只是围绕来自

    所以,我在这里要做的是传递一个 data Config = Config { clusterState :: MVar ClusterState } Process 也会这样!)。可能与 ReaderT IO 过程 ReaderT Config Process 你自己

    重复Michael的博客帖子: 斯塔特 在某种程度上。我鼓励大家阅读这些帖子,它们对我来说非常鼓舞人心,因此,它们再次出现在这里:

    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