Haskell将不确定性与错误处理相结合

问题描述

假设我正在创建一个简单的解释器,该解释器可能会引发错误,例如

type Error = String

data Term = Con Int | Div Term Term

eval :: (MonadError Error m) => Term -> m Int
eval (Con a) = return a
eval (Div u v) = do
  a <- eval u
  b <- eval v
  if b == 0 then
    throwError "Division by zero"
  else
    return $ a `div` b

具体错误处理程序的典型选择是Either Error

runEval :: Term -> Either Error Int
runEval = eval

现在假设我要扩展此解释器以处理非确定性。例如,我可以添加一个术语Choice Term Term,它可以求值第一个或第二个参数。

data Term = Con Int | Div Term Term | Choice Term Term

然后我可以将具体评估表示为[Either Error Int],其中列表中的每个项目代表一个可能的评估。但是,我在如何在不修改Choiceeval情况下将Con情况添加到Div函数中的问题中。

我尝试过的事情:

eval :: (MonadError Error m,MonadPlus m) => Term -> m Int
-- The Con and Div cases remain unchanged.
eval (Choice u v) = do
  w <- return u `mplus` return v  -- pick either u or v
  eval w

runEval :: Term -> [Either Error Int]
runEval = runExceptT . eval

但是,这只会返回第一个可能的结果,而不会回溯。

> let t = Con 1 `Div` (Choice (Con 0) (Con 1))
> runEval t
[Left "Division by zero"]

我期望的是:[Left "Division by zero",Right 1]

结合非确定性和错误处理的正确方法是什么?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)