haskell - Haskell Wikibook - 广义代数数据类型练习 - Maybe and Either
问题描述
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
,但我不确定如何正确地做到这一点(使用模式匹配?)
提前致谢!
解决方案
是的,使用模式匹配,甚至可能是Maybe
monad。
您可以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
(由于Maybe
monad 的实现方式) ,它将自动返回fail
。
eval (Add e1 e2) = do
Left i1 <- eval e1
Left i2 <- eval e2
return (Left (i1 + i2))
推荐阅读
- python - ParseException: u"\nextraneous 输入 '/' 期待 {'SELECT', 'FROM', 'ADD',
- php - 通过特定键将元素从数组传递到数据库
- javascript - Javascript:意外的令牌 [ 在第 92 行
- regex - Scalability of Regular Expressions (MarkLogic)
- multithreading - Play Framework Scala thread affinity
- python - Linprog 可以解决 LP 原始问题但不能解决对偶问题?
- acumatica - 将详细信息网格添加到销售类别 (IN204060) - 父/子问题
- c# - C# HttpClient 通过代理:CONNECT 请求
- postgresql - Batch Conditional INSERT INTO statement in Postgres
- android - Android 深度链接路径模式