在示例中将IO monad与State monad相结合



我为语句创建了简单的计算器。我想使用变压器来实现这一点-将IO monad与State混合
有人能解释一下怎么做吗?这是我无法处理的事情——变形金刚。

execStmt :: Stmt -> State (Map.Map String Int) ()
execStmt s = case s of
      SAssigment v e -> get >>= (s -> put (Map.insert v (fromJust (runReader (evalExpM e) s)) s))
      SIf e s1 s2 -> get >>=  (s -> case (fromJust (runReader (evalExpM e) s)) of
                                        0 -> execStmt s2
                                        _ -> execStmt s1
                              )
      SSkip -> return ()
      SSequence s1 s2 -> get >>= (s -> (execStmt s1) >>= (s' -> execStmt s2))
      SWhile e s1 -> get >>= (s -> case (fromJust (runReader (evalExpM e) s)) of
                                        0 -> return ()
                                        _ -> (execStmt s1) >>= (s' -> execStmt (SWhile e s1)))
execStmt' :: Stmt -> IO ()
execStmt' stmt =  putStrLn $ show $ snd $ runState (execStmt  stmt) Map.empty

以下是的基本程序大纲

newtype StateIO s a = SIO {runSIO :: s -> IO (a, s)}
put :: s -> StateIO s ()
put s' = SIO $ _s -> return ((), s')
liftIO :: IO a -> StateIO s a
liftIO ia = SIO $ s -> do
    a <- ia
    return (a, s)
instance Functor (StateIO s) where
    fmap ab (SIO sa) = SIO $ s -> do
        (a, s') <- sa s
        let b = ab a
        return (b, s')
instance Applicative (StateIO s) where
    pure a = SIO $ s -> return (a, s)
    (SIO sab) <*> (SIO sa) = SIO $ s -> do
        (ab, s' ) <- sab s
        (a , s'') <- sa  s'
        let b = ab a
        return (b, s')

StateIO s a是接受输入状态(类型为s)的东西,并返回IO操作以产生类型为a的东西以及新状态。

要检查是否理解,请执行以下

  • 写入一个值get :: StateIO s s,用于检索状态
  • Monad (StateIO s)编写一个实例(它将类似于上面的代码)
  • 最后,这是理解transformers的重要一步,就是定义newtype StateT m s a = StateT {run :: s -> m (a, s)},并将上面的代码转换为Monad m。这将向您展示monad转换器是如何工作的

最新更新