0

ステートメントの簡単なエバリュエーターを作成しました。トランスフォーマーを使用してそれを行いたいと思います-IOモナドと状態を混ぜます。
誰かがそれを行う方法を説明できますか? それは私が対処できないものです-トランスフォーマー。

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
4

1 に答える 1

3

基本的なプログラム概要はこちら

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)記述します (上記のコードに似ています)。
  • 最後に、これはトランスフォーマーを理解するための大きなステップであり、 を定義しnewtype StateT m s a = StateT {run :: s -> m (a, s)}、上記のコードをそれに (制約付きでMonad m) 変換することです。これにより、モナド変換子がどのように機能するかがわかります。
于 2016-04-13T19:24:33.287 に答える