Haskell Wikibook-广义代数数据类型练习-也许是这样

时间:2018-11-20 16:17:56

标签: haskell

this page of the Haskell Wikibook上有一个练习,可让您使用Maybe和Either来完成一个场景(大概表明用例很痛苦)。

练习是:

data Expr = I Int
        | B Bool           -- boolean constants
        | Add Expr Expr
        | Mul Expr Expr
        | Eq  Expr Expr    -- equality test

eval :: Expr -> Maybe (Either Int Bool)
-- Your implementation here.

解决方案的第一行-我想-​​很简单:

data Expr = I Int         -- integer constants
          | B Bool        -- boolean constants
          | Add Expr Expr -- add two expressions
          | Mul Expr Expr -- multiply two expressions
          | Eq  Expr Expr -- equality test
          deriving (Show)

eval :: Expr -> Maybe (Either Int Bool)
eval (I n) = Just $ Left n
eval (B b) = Just $ Right b
eval (Add e1 e2) = ...
eval (Mul e1 e2) = ...
eval (Eq e1 e2) = ...

但是我不确定如何定义其余部分。举例来说,我猜想add需要解压缩每个表达式的fromLeftfromJust,但是我不确定如何正确执行此操作(使用模式匹配吗?)

谢谢!

2 个答案:

答案 0 :(得分:4)

是的,具有模式匹配,甚至还有Maybe单子。

您可以仅使用模式匹配来实现eval (Add e1 e2)分支:

eval (Add e1 e2) = case eval e1 of
    Just (Left i1) -> case eval e2 of
        Just (Left i2) -> Just (Left (i1 + i2))
        _ -> Nothing
    _ -> Nothing

在一对上进行模式匹配是减少嵌套case语句数量的一种好方法:

eval (Add e1 e2) = case (eval e1, eval e2) of
    (Just (Left i1), Just (Left i2)) -> Just (Left (i1 + i2))
    _ -> Nothing

或者,您可以将Maybe monad用作对这些case语句的抽象。如果Nothing块绑定中任何模式匹配失败(由于do monad如何实现fail),它将自动返回Maybe

eval (Add e1 e2) = do
    Left i1 <- eval e1
    Left i2 <- eval e2
    return (Left (i1 + i2))

答案 1 :(得分:1)

  

eval(添加e1 e2)= ...

您将要评估e1e2,然后根据这些结果进行模式匹配。有多种方法可以做到这一点。例如,您可以使用let绑定。

let ev1 = eval e1
    ev2 = eval e2 
in  

然后使用case构造进行模式匹配。或者,如果您愿意的话,也可以不使用let绑定

case (eval e1, eval e2) of 

和该对上的图案匹配。