Matching several patterns simultaneously in case (aka MultiCase)

3,007 views
Skip to first unread message

Esad Hajdarevic

unread,
Jan 12, 2016, 5:08:23 PM1/12/16
to Elm Discuss
Hi everyone, this is my first post to elm-discus :)

Please let me know if this has already been discussed somewhere - I couldn't find anything about it.

Currently, in a case expression, it's not possible to specify multiple patterns that all resolve to a same expression.

For example, in order to return number of days in a month, one has to write something like:

let days =
  case month of
    January -> 
      31
    February ->
      28 -- ignore leap year logic for simplicity
    March ->
      31
    April ->
      30
    May ->
      31
    ...

With support for multiple patterns per match, the above could be expressed as:

let days = 
  case month of
    January | March | May | ... -> 
      31
    February -> 
      28
    April | June | ... ->
      30
  
Related discussion about MultiCase from the Haskell Wiki: https://wiki.haskell.org/MultiCase

Best,

Esad

Esad Hajdarevic

unread,
Jan 12, 2016, 5:10:43 PM1/12/16
to Elm Discuss
Sorry about the lack of a question at the end :) - I copied the text from elm-proposals where it was implicit that it was a proposal. So, what do you think about adding this to Elm?


Joey Eremondi

unread,
Jan 12, 2016, 5:27:00 PM1/12/16
to elm-d...@googlegroups.com

I'll respond in more depth when not on my phone. But an initial point for thought? What happens when there are arguments to the constructors in a multiple match?

On Jan 12, 2016 2:10 PM, "Esad Hajdarevic" <es...@esse.at> wrote:
Sorry about the lack of a question at the end :) - I copied the text from elm-proposals where it was implicit that it was a proposal. So, what do you think about adding this to Elm?


--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alexandre Galays

unread,
Jan 12, 2016, 5:33:02 PM1/12/16
to Elm Discuss
Seems good; Scala also shares this syntax and I find it very intuitive.

Evan Czaplicki

unread,
Jan 12, 2016, 6:33:24 PM1/12/16
to elm-d...@googlegroups.com
OCaml probably was the first language to have this. Guarded branches is also a sometimes useful feature that exists in Haskell and probably SML and OCaml.

They can make things kind of messy, but when used carefully, they are nice. All of these make sense to me, but of all the ways things could be improved, this is not a major priority. It is available in syntax, and it does not clash with anything. So it can be added at any time. The only question is "is this more urgent than all the other things?"

I'm in the process of learning a lot more about Erlang, so I would like to get more perspective on what exactly is needed from that perspective before I start committing to these sorts of things.

Esad Hajdarevic

unread,
Jan 12, 2016, 6:57:42 PM1/12/16
to Elm Discuss
In OCaml, you'd get a compile error (Variable .. must occur on both sides of this | pattern") unless you have really the same set of variables in every alternative.

That means that matching something like

match color with
   | RGB (r,g,b) | Gray v -> ...

won't work, but for example

   | RGB (_,g,_) | Gray g -> g

works (as long as g has same type in both constructors).

Esad Hajdarevic

unread,
Jan 12, 2016, 7:13:04 PM1/12/16
to Elm Discuss

OCaml probably was the first language to have this. Guarded branches is also a sometimes useful feature that exists in Haskell and probably SML and OCaml.


Guards are also nice and could alone be used to deal with some simple cases  (something like "case _ when List.member month [Jan, Mar, ...]"). This has of course implications on exhaustiveness check, but how all this works could really be just borrowed from OCaml :)
 
They can make things kind of messy, but when used carefully, they are nice. All of these make sense to me, but of all the ways things could be improved, this is not a major priority. It is available in syntax, and it does not clash with anything. So it can be added at any time. The only question is "is this more urgent than all the other things?"


Of course this falls into "nice to have" bucket, but it would be really nice if it could make it into the language some day.
 
I'm in the process of learning a lot more about Erlang, so I would like to get more perspective on what exactly is needed from that perspective before I start committing to these sorts of things.


Which parts from Erlang look like worth borrowing so far? :) (I was thinking the other day that elm architecture is little bit like message passing in Erlang, albeit within a single process).

 

Laszlo Pandy

unread,
Jan 12, 2016, 7:20:38 PM1/12/16
to elm-d...@googlegroups.com
Evan, please keep this in mind as you check out Erlang because this is delightful feature which makes us programmers feel warm feelings for Elm and would be pretty straightforward to implement. (I might have just hacked it into elm-compiler in the last half hour instead of going to bed; but it duplicates the branch for each other pattern so if something goes wrong you get duplicate error message ;))

Aaron VonderHaar

unread,
Jan 12, 2016, 8:41:51 PM1/12/16
to elm-d...@googlegroups.com
Are there better examples of ways this feature would be useful? The
days/months example seems like it's easier to read when each month is
listed out in calendar order, instead of being grouped by number of
days. The color example seems questionable--there are a few color
functions you would be able to implement by fancy matches, but most
would require arithmetic.

I think in most cases the desire for multimatching is a smell
indicating that you should change how you model your data to eliminate
duplication. Does anyone have examples of where multimatching was a
significant benefit?

Laszlo Pandy

unread,
Jan 13, 2016, 2:01:42 AM1/13/16
to elm-d...@googlegroups.com
Yes. In the past we have discussed the advantage of explicitly listing all constrictors instead of using a wildcard for the last pattern. The advantage here is that when a new constructor is added the compiler will tell you to check your case expression to handle the new case. If you use the catch all underscore you lose this benefit.

Given that, I would say that using catch all pattern could be a smell: it means that you might forget to update it if the data type is extended. 

dieter.k...@gmail.com

unread,
Jan 28, 2016, 12:44:54 PM1/28/16
to Elm Discuss
I was looking for this feature as well.

We’ve a game client, which receives game events via a socket. Different components
are interested in different events, which are modeled as a union type. Now for some components
the most events result in a NoOp.

It would be nice to group all the NoOp cases together in a multi match. We used wildcard as well,
but this often resulting in bugs where a specific event was unintentionally not handled by a component and therefore resulted in a NoOp.
Reply all
Reply to author
Forward
0 new messages