我有三个版本的功能,如下所示。 #2和#3工作。 #2现在是我的第一选择。我想找到一些让#1工作的方法,看看它是如何比较的。它在底部。
首先,我有这种类型:
data Value =
IntVal Int
| BoolVal Bool
deriving (Show)
这个(a的工作片段)功能:
-- #2
evaluate (If ec et ef) s0 =
case vc of
(IntVal ____) -> error "Conditional expression in If statement must be a boolean"
(BoolVal vcb) -> if vcb then (vt, st)
else (vf, sf)
where (vc, sc) = evaluate ec s0
(vt, st) = evaluate et sc
(vf, sf) = evaluate ef sc
我想知道我是否可以摆脱案件陈述并使用警卫代替。我可以在case语句中使用guards ,我发现这有效:
-- #3
evaluate (If ec et ef) s0 =
case vc of
(IntVal _) -> error "Conditional expression in If statement must be a boolean"
(BoolVal vcb) | vcb -> (vt, st)
| otherwise -> (vf, sf)
where (vc, sc) = evaluate ec s0
(vt, st) = evaluate et sc
(vf, sf) = evaluate ef sc
很高兴知道。我认为#2最清楚地传达了我的意图。尽管如此,这是我尝试的第一件事,我想弄清楚它是如何实际运作的:
-- #1
evaluate (If ec et ef) s0
| (IntVal vc) = error "Conditional expression in If statement must be a boolean"
| vc == True = (vt, st)
| otherwise = (vf, sf)
where (vc, sc) = evaluate ec s0
(vt, st) = evaluate et sc
(vf, sf) = evaluate ef sc
这会产生以下错误。看起来我需要一些东西来询问Value类型的某些东西是否也是IntVal子类型?:
Couldn't match expected type `Int' with actual type `Value'
In the first argument of `IntVal', namely `vc'
In the expression: (IntVal vc)
--------------------------------------------------------------------------------
Couldn't match expected type `Bool' with actual type `Value'
In the expression: (IntVal vc)
In a stmt of a pattern guard for
an equation for `evaluate':
(IntVal vc)
如何解决这些错误并实施无案例,仅限警卫?
答案 0 :(得分:5)
这不是一个真正的答案,但我写的是这样的事情:
evaluate (If ec et ef) s0 =
case evaluate ec s0 of
(True, sc) -> evaluate et sc
(False, sc) -> evaluate ef sc
我发现vt
,st
,vf
和sf
的命名更难以阅读,因为我必须自己跟踪这些变量的数据流。保持他们的匿名简化了理解。
答案 1 :(得分:4)
你的#1的问题在于,普通的守卫只能是布尔表达式,它们无法简洁地匹配模式。所以IntVal vc
不会像一个人一样工作。即使这样做,您从vc
模式获得的IntVal vc
也不能用作Bool
值 - 您需要BoolVal vc
模式。
但是,您可以使用pattern guards:
evaluate (If ec et ef) s0
| IntVal _ <- vc = error "Conditional expression in If statement must be a boolean"
| BoolVal True <- vc = (vt, st)
| BoolVal False <- vc = (vf, sf)
where (vc, sc) = evaluate ec s0
(vt, st) = evaluate et sc
(vf, sf) = evaluate ef sc
答案 2 :(得分:1)
如果您使用record syntax重新定义类型Value
:
data Value = IntVal { unInt :: Int } | BoolVal { unBool :: Bool }
然后你可以这样做:
evaluate (If ec et ef) s0 =
if unBool vc then (vt, st) else (vf, sf)
where (vc, sc) = evaluate ec s0
(vt, st) = evaluate et sc
(vf, sf) = evaluate ef sc