Haskell错误处理程序

时间:2015-03-11 00:39:40

标签: haskell

我正在努力尝试在Haskell中编写错误处理程序。我的Haskell技能非常糟糕。有些知识渊博的人能告诉我如何纠正这个评价吗?

data Checked a = Good a | Error String

evaluate :: Exp -> Env -> Checked Value
evaluate (Call fun arg) env =
  case evaluate fun env of
    Error msg -> Error (msg ++ "Error")
    Good func ->
      case evaluate arg env of
        Error msg -> Error (msg ++ "error")
        Good arg0 -> 
          let ClosureV x body env' = av
            evaluate body ((x, arg0) : env')

我知道它需要返回一个Checked Value,但不知道如何写入。

1 个答案:

答案 0 :(得分:1)

你几乎成了你的第一个单子。

让我们看一下evaluate (Call fun arg) env的主体。

evaluate (Call fun arg) env =
  case evaluate fun env of
    Error msg -> Error msg
    Good func ->
      case evaluate arg env of
        Error msg -> Error msg
        Good arg0 ->
          ...

这里有一个模式。如果我们将两个case放在彼此的顶部,它将如下所示,███的第一个混乱来自于arg的顶部输入单词fun 1}}而第二个问题来自在arg0

的顶部输入单词func
case evaluate ███ env of
  Error msg -> Error msg
  Good ████ ->
    ...

在这两种情况下,我们都在研究一些Checked a。我们将一些Checked值传递给case表达式并执行其他操作,如果选中的值为Good,则还会产生一些选中的值。让我们忽略evaluate部分

中的所有内容
case ███ of
  Error msg -> Error msg
  Good ████ ->
    ...

我们反复使用这种模式,所以让我们提取它。

whenGood :: Checked a -> (a -> Checked b) -> Checked b
whenGood checked next = case checked of
                            Error msg -> Error msg
                            Good  x   -> next  x

现在我们可以将evaluate (Call fun arg) env等效地写为

evaluate (Call fun arg) env =
    whenGood (evaluate fun env) $ \func ->
      whenGood (evaulate arg env) $ \arg0 ->
        ...

我们不需要缩进(lambdas尽可能向右延伸),并且可以将whenGood写为中缀运算符。这看起来很不错。

evaluate (Call fun arg) env =
    evaluate fun env `whenGood` \func ->
    evaluate arg env `whenGood` \arg0 ->
    ...

whenGood的类型与>>=的{​​{1}}类型匹配。

Monad

要定义whenGood :: Checked a -> (a -> Checked b) -> Checked b (>>=) :: Monad m => m a -> (a -> m b) -> m b ,我们还需要Monad类型return。您的a -> m a构造函数会将值Good放入a

Checked a

我断言return :: Monad m => a -> m a Good :: a -> Checked a whenGood服从Good(>>=)的{​​{3}},因此我们可以return } Monad

的实例
Checked

拥有instance Monad Checked where return = Good (>>=) = whenGood 个实例意味着我们可以使用Monad laws中的任何一个。它还允许我们使用更熟悉的Monad运算符代替evaluate (Call fun arg) env来编写>>=

whenGood

甚至是evaluate (Call fun arg) env = evaluate fun env >>= \func -> evaluate arg env >>= \arg0 -> ... 符号

do

如果您有更新的GHC,可能会抱怨evaluate (Call fun arg) env = do func <- evaluate fun env arg0 <- evaluate arg env ... 需要Monad个实例,如果是,您可以设置默认值。

Applicative