Haskell多语句效率

时间:2011-08-15 23:21:11

标签: haskell performance case

这对于检查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"

3 个答案:

答案 0 :(得分:7)

有时很难想出这个问题的小例子,这些例子看起来并不人为,但确实发生了。有时你需要一堆计算结果来弄清楚如何将一个函数拆分成它的情况。

所以,是的,我经常发现在事物元组中使用case是最干净的 - 我可能会关心构建复杂的决策过程。我相信懒惰来计算解析要调用的分支所需的最小值。

值得尝试通过布尔警卫(甚至模式保护)来表达你的测试,但有时候没有什么可以在大元组中列出你需要的计算值,然后为每个有趣的环境组合写一行。

答案 1 :(得分:1)

假设关注效率非常重要,并且不是过早优化,那么您应该针对最常见的情况进行优化;我认为,即使在Haskell中,也意味着您希望将True,True,True个案例放在首位。

实际上,在给定的情况下,如果x == 10x == 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")]