【问题标题】:Haskell and multiple conditionsHaskell 和多个条件
【发布时间】:2016-05-01 01:54:45
【问题描述】:

如果我有多个仅略有不同的条件,那么编写以下形式的函数(考虑和无法嵌套守卫)的最佳方法是:

f | a && b && c  = 1
  | a && b && d  = 2
  | a && b && e  = 3
  | a && g && e  = 4

想象一下有更多更多的条件。理想情况下,我想编写一个嵌套的 if 来检查 a then b 然后是别的东西,但有人告诉我这在 Haskell 中是不可能的。

另外,在示例中。如果第一行返回fall,如果条件a和b没有在where子句中定义,是否再次检查?

【问题讨论】:

  • 谁告诉你嵌套ifs 不可能在 Haskell 中告诉你错了。像这样的构造是完全可能的:if a then if b then A else if c then B else C else D。只是这通常被视为有点“不负责任”。您最关心的是什么,可读性、可维护性或效率?
  • @AndreyChernyakhovskiy 最终提高了效率,但又不会牺牲其他两个方面的太多。我上面写的似乎不是很有效,而且,因为我正在学习,我希望我的代码尽可能“haskelly”:P
  • 效率只能通过基准测试来衡量。至于“haskelliness”,遵循一些常见的模式不是教条。毕竟,这是你自己的判断。如果您认为您的程序以 ifs 的树形式布局时读取最清晰,最好这样做。
  • 一种可能的“haskelly”方式是这样的:f = let f' True True True _ _ _ = 1; f' True True _ True _ _ = 2; f' True True _ _ True _ = 3; f' True _ _ _ True True = 4; f' _ _ _ _ _ _ = 5 in f' a b c d e g
  • 除非abc 等是计算成本很高的表达式(在这种情况下,您应该使用let 绑定来确保共享),重复相同守卫可能是一个更好的解决方案:可读性比假设的轶事性能提升更有价值。

标签: haskell if-statement conditional-statements


【解决方案1】:

在这种情况下,if 语句的问题不是它们不能嵌套,而是它们总是必须有一个 else 组件,这使得它们在这种情况下非常笨拙,因为你必须包含每个语句中的后备案例。您在 if 语句中的示例看起来像这样。

f = if a then 
     if b then 
      if c then 1
       else if d then 2
        else if c
          then 3
          else 5
     else 5
    else if g then 
     if e
      then 4
      else 5
     else 5

至于您的其他选择,这完全取决于具体情况。如ab等。是f 的参数,那么您可以在函数上进行模式匹配。

f True True True False False False False = 1
f True True False True False False False = 2
f True True False False True False False = 3
f True False False False True False True = 4
f _    _    _     _     _    _     _     = 5

但是,如果变量是全局变量,或者在 where 子句中定义,则需要使用 case 语句。

f =
  case (a, b, c, d, e, f, g) of
    (True, True, True, _, _, _, _) -> 1
    (True, True, _, True, _, _, _) -> 2
    (True, True, _, _, True, _, _) -> 3
    (True, _, _, _, True, _, True) -> 4
    _                              -> 5

不过,实际上,只要您的变量名不是太长,您的解决方案可能是可读性和简洁性的最佳组合。至于效率,布尔运算是如此便宜,除非这个函数包含在一个非常密集的算法中的某个紧密循环中,否则我怀疑你将能够看到这些选项之间的速度差异。

【讨论】:

    【解决方案2】:

    我会使用case

    f x y z =
      case (a, b, c, d, e, f, g) of
        (True, True, True, _, _, _, _) -> 1
        (True, True, _, True, _, _, _) -> 2
        (True, True, _, _, True, _, _) -> 3
        (True, _, _, _, True, _, True) -> 4
      where
        a = ...
        b = ...
        c = ...
    

    由于这些案例并非排他性的,因此您需要确保订单和/或覆盖范围符合您的预期。

    【讨论】:

      猜你喜欢
      • 2016-02-04
      • 2015-10-14
      • 2013-10-06
      • 1970-01-01
      • 1970-01-01
      • 2012-09-28
      • 1970-01-01
      • 2016-08-29
      • 2021-12-02
      相关资源
      最近更新 更多