Haskell中的Or模式

Jon*_*ent 24 ocaml haskell

在OCaml中,我习惯于编写如下代码:

let combine o1 o2 = match o1, o2 with
    | Valid, Invalid | Invalid, Valid -> Invalid
    | _ -> ...
Run Code Online (Sandbox Code Playgroud)

我没有找到在Haskell中编写或模式的方法,我真的很想念它.有没有人有办法解决吗?

ben*_*ofs 19

我不认为这在haskell中是可能的.但是,有一些替代方案:

使用where绑定来排除公共代码

这在您的示例中没有多大意义,但如果您在case表达式的主体中有更多代码,那么它很有用:

combine o1 o2 = case (o1,o2) of
  (Valid, Invalid) -> handleInvalid
  (Invalid, Valid) -> handleInvalid
  ...
 where
  handleInvalid = ...
Run Code Online (Sandbox Code Playgroud)

使用通配符模式

根据我的经验,你不想经常想要在一个模式匹配中使用两个或模式.在这种情况下,您可以处理所有"好"的情况,并使用外卡模式:

combine o1 o2 = case (o1,o2) of
  (Valid, Valid) -> Valid -- This is the only valid case
  _              -> Invalid -- All other cases are invalid
Run Code Online (Sandbox Code Playgroud)

这样做的缺点是它绕过穷举检查程序,并且您不能将通配符模式用于其他目的.

使用警卫和 ==

如果要匹配的类型是类似枚举的类型,则可以考虑创建Eq实例.然后你可以使用==||匹配一个后卫中的多个构造函数:

combine o1 o2
  | o1 == Invalid && o2 == Valid || o1 == Valid && o2 == Invalid = Invalid
  | ...
Run Code Online (Sandbox Code Playgroud)

我同意这看起来不太好,它也有绕过穷举检查器的缺点,并且如果模式重叠则不会警告你,所以我不推荐它.

  • 使用`Eq`实例,您还可以编写``(o1,o2)`elem` [(无效,有效),(有效,无效)]``.但是,平等并不好 - 模式匹配是可取的. (3认同)
  • 我喜欢如何在“`where`”解决方案中保存一个 lambda,OCaml 程序员自然会插入一个。 (2认同)

aav*_*ogt 7

你可以使用这个quasiquoter http://hackage.haskell.org/package/OrPatterns.您的示例转换为:

let combine o1 o2 = case (o1, o2) of
      [o| (Valid, Invalid) | (Invalid, Valid ) |] -> Invalid
      _ -> ...
Run Code Online (Sandbox Code Playgroud)