【问题标题】:Combining State monad with Either-style error propagation将 State monad 与 Either-style 错误传播相结合
【发布时间】:2020-03-10 17:19:18
【问题描述】:

我对 Haskell 很陌生。我试图通过将 Either 视为 monad 来将 State monad 与错误传播结合起来。我想以不需要显式处理状态或错误的方式递归抽象语法树(例如,用于在语句和表达式上编写解释器)。我的印象是,最简单的方法是使用 exceptT monad 转换器。这是我的编译示例代码:

import Control.Monad.Except
import Control.Monad.State
import qualified Data.Map.Strict as M

-- simple expression language supporting crude let bindings
data Exp = Lit Int | Var String
         | Add (Exp, Exp) | Let (String, Exp, Exp) deriving Show

okExp =  -- let x = 2 in let y = x + 3 in x + y -- evaluate to 7
    Let ("x", Lit 2,
             Let ("y", Add (Var "x", Lit 3),
                      Add (Var "x", Var "y")))
badExp = Var "x"  -- error: x is not defined

type St = M.Map String Int
initialState :: St
initialState = M.empty

type EvalMonad = ExceptT String (State St)

evalExp :: Exp -> EvalMonad Int
evalExp (Lit n) = return n
evalExp (Var v) = do
    mp <- lift get
    case M.lookup v mp of
        Just i -> return i
        Nothing -> throwError (v ++ " not found")
evalExp (Add (a, b)) = do
    x <- evalExp a
    y <- evalExp b
    return (x + y)

我希望在简单的示例(例如,okExp、badExp)上运行 evalExp。我不确定三件事:

  1. 如何将初始状态纳入计算?
  2. 如何使用 runExceptT 提取结果?
  3. (更笼统):这是解决此问题的“正确”方法吗?

【问题讨论】:

  • 我想我会data Exp = ... | Add Exp Exp | Let String Exp Exp。为每个复杂表达式添加额外的元组构造函数间接是没有意义的。
  • 谢谢,我一直想知道为什么元组通常在此内容中使用,因为我通常不打算对它们使用柯里化,但这很有意义.

标签: haskell monad-transformers state-monad either


【解决方案1】:

看起来是一个很好的开始!这是一个小例子,展示了如何在 ghci 中同时使用 runExceptTrunState

> runState (runExceptT (evalExp (Add (Lit 3, Lit 4)))) initialState
(Right 7,fromList [])
> runState (runExceptT (evalExp (Add (Lit 3, Var "x")))) initialState
(Left "x not found",fromList [])

【讨论】:

  • 太好了,谢谢。那么我认为,这种配对似乎是正确的方法?
  • @blandish 是的,这是非常常见和惯用的定义 monad 转换器堆栈来描述您正在解释的语言的可能副作用。
  • @blandish 一个有趣的练习是考虑如果您切换变压器的顺序会发生什么变化:StateT St (Except String)
  • @luqui 这很有帮助;我会试试这个练习。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2011-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-09
  • 1970-01-01
  • 2021-01-04
相关资源
最近更新 更多