我正在努力尝试在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,但不知道如何写入。
答案 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