这对于检查Haskell中的多个语句有效吗?或者这有更好的方法吗?
case ((x > -10) && (x < 20),x /= 9,(x `mod` 2) == 0,x) of
(False,_,_,_) -> error "Not in range"
(_,False,_,_) -> error "Must not be 9"
(_,_,False,_) -> error "Must be even"
(True,True,True,10) -> stuff ()
(True,True,True,20) -> stuff ()
_ -> error "Error Message"
答案 0 :(得分:7)
有时很难想出这个问题的小例子,这些例子看起来并不人为,但确实发生了。有时你需要一堆计算结果来弄清楚如何将一个函数拆分成它的情况。
所以,是的,我经常发现在事物元组中使用case
是最干净的 - 我可能会关心构建复杂的决策过程。我相信懒惰来计算解析要调用的分支所需的最小值。
值得尝试通过布尔警卫(甚至模式保护)来表达你的测试,但有时候没有什么可以在大元组中列出你需要的计算值,然后为每个有趣的环境组合写一行。
答案 1 :(得分:1)
假设关注效率非常重要,并且不是过早优化,那么您应该针对最常见的情况进行优化;我认为,即使在Haskell中,也意味着您希望将True,True,True
个案例放在首位。
实际上,在给定的情况下,如果x == 10
或x == 20
您不需要进行其他测试 - 您甚至不需要构建thunk计算它们;并且编译器无法知道(没有配置文件引导优化)哪个是最常执行的代码路径,而你应该有一个合理的猜测(通常你需要分析来验证)。
所以你想要的是以下(未经测试):
case x of
10 -> stuff ()
20 -> stuff ()
_ -> case ((x > -10) && (x < 20),x /= 9,(x `mod` 2) == 0) of
(False,_,_) -> error "Not in range"
(_,False,_) -> error "Must not be 9"
(_,_,False) -> error "Must be even"
_ -> error "Error Message"
免责声明:我没有验证此代码和所有优化后的原始代码会发生什么。
答案 2 :(得分:0)
这是怎么回事?您按顺序检查条件,并在第一个条件下返回失败的条件,因此将条件放入列表并搜索它。
fn x = case lookup False conds of
Just ohno -> error ohno
Nothing
| x == 10 -> stuff
| x == 20 -> stuff
| otherwise -> error "Error Message"
where
conds = [
(x > -10 && x < 20, "Not in range"),
(x /= 9, "Must not be 9"),
(even x, "Must be even")]