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
需要解压缩每个表达式的fromLeft
,fromJust
,但是我不确定如何正确执行此操作(使用模式匹配吗?)>
谢谢!
答案 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)= ...
您将要评估e1
和e2
,然后根据这些结果进行模式匹配。有多种方法可以做到这一点。例如,您可以使用let
绑定。
let ev1 = eval e1
ev2 = eval e2
in
然后使用case
构造进行模式匹配。或者,如果您愿意的话,也可以不使用let
绑定
case (eval e1, eval e2) of
和该对上的图案匹配。