Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Or-patterns in Haskell

Tags:

haskell

ocaml

In OCaml, I was used to writing code which looked like:

let combine o1 o2 = match o1, o2 with     | Valid, Invalid | Invalid, Valid -> Invalid     | _ -> ... 

I didn't find a way to write or-patterns in Haskell and I really miss it. Does anyone have a solution?

like image 958
Jonathan Laurent Avatar asked Jul 11 '14 14:07

Jonathan Laurent


People also ask

What is a pattern in Haskell?

We use pattern matching in Haskell to simplify our codes by identifying specific types of expression. We can also use if-else as an alternative to pattern matching. Pattern matching can also be seen as a kind of dynamic polymorphism where, based on the parameter list, different methods can be executed.

What does pattern matching mean in Haskell?

Pattern matching consists of specifying patterns to which some data should conform and then checking to see if it does and deconstructing the data according to those patterns. When defining functions, you can define separate function bodies for different patterns.

What is XS Haskell?

(x:xs) is a pattern that matches a non-empty list which is formed by something (which gets bound to the x variable) which was cons'd (by the (:) function) onto something else (which gets bound to xs ).

What is otherwise in Haskell?

It's not equivalent to _ , it's equivalent to any other identifier. That is if an identifier is used as a pattern in Haskell, the pattern always matches and the matched value is bound to that identifier (unlike _ where it also always matches, but the matched value is discarded).


1 Answers

I don't think this is possible in haskell. There are however, a few alternatives:

Factor out the common code with a where binding

This doesn't make much sense in your example, but is useful if you have more code in the body of the case expression:

combine o1 o2 = case (o1,o2) of   (Valid, Invalid) -> handleInvalid   (Invalid, Valid) -> handleInvalid   ...  where   handleInvalid = ... 

Use wildcard patterns

In my experience, it doesn't happen so often that you want to use two or patterns in one pattern match. In this case, you can handle all the "good" cases and the use a wild card pattern for the rest:

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

This has the disadvantage that it bypasses the exhaustiveness checker and that you cannot use wildcard patterns for other purposes.

Use guards and ==

If the types you want to match against are enum-like types, you might consider making an Eq instance. Then you can use == and || to match multiple constructors in one guard:

combine o1 o2   | o1 == Invalid && o2 == Valid || o1 == Valid && o2 == Invalid = Invalid   | ... 

I agree that this doesn't look as nice and it also has the disadvantage of bypassing the exhaustiveness checker and doesn't warn you if patterns overlap, so I wouldn't recommend it.

like image 64
bennofs Avatar answered Sep 21 '22 08:09

bennofs