![](/img/trans.png)
[英]Is it possible to rewrite this Haskell function using guards with no case-of?
[英]How can I rewrite this Haskell using guards with no case-of?
我有三个版本的功能,如下所示。 #2和#3工作。 #2现在是我的第一选择。 我想找到一些让#1工作的方法,看看它是如何比较的。 它在底部。
首先,我有这种类型:
data Value =
IntVal Int
| BoolVal Bool
deriving (Show)
而这个(工作片段)功能:
-- #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语句中后卫,我发现这工作:
-- #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)
如何解决这些错误并实现无案例,仅限警卫的实施?
这不是一个真正的答案,但我会写下这样的事情:
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的问题在于,普通的守卫只能是布尔表达式,它们无法简洁地匹配模式。 所以IntVal vc
就不会像一个人一样工作。 而且即使这样做了, vc
你从得到IntVal vc
模式不能被用作一个Bool
值-你需要的BoolVal vc
该模式。
但是,您可以使用图案保护 :
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
如果使用记录语法重新定义类型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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.