edgerunner
edgerunner

Reputation: 14973

Generic pattern matching in Elm

I'm trying to build a generic mapping function that will extract a possible inner type from a union type, apply a transform to the inner value and map it back to the outer type.

The trouble is, I need a way to distinguish if a specific value of the outer type has an inner type at all.

It would work for me if the code below actually compiled, but Elm doesn't allow constants in pattern matches. (constructor on line 4 fails to compile)

Is there any other way to accomplish this?

map : (inner -> outer) -> (inner -> inner) -> outer -> outer
map constructor func current =
    case current of
        constructor child ->
            constructor (func child)

        _ ->
            current

Upvotes: 3

Views: 203

Answers (2)

Aleksei astynax Pirogov
Aleksei astynax Pirogov

Reputation: 2491

You can take a look to the elm-accessors library. With it you will need to define a Relation for every of yours type constructor (it is pretty straightforward). But then you'll be free to use a good old List.map to map over any constructor!

Here is a usage example:

type FooBar a b
  = Foo a
  | Bar b

items =
   List.map
     (over (foo << try) ((+) 1)           -- affects only "Foo"s
      << 
      over (bar << try) (\b -> b ++ "!")) -- affects only "Bar"s
     [Foo 1, Bar "a", Foo 10]
-- = [Foo 2,Bar "a!",Foo 11]

Here is a live version (Ellie).

Upvotes: 1

Gareth Latty
Gareth Latty

Reputation: 88977

No, unfortunately Elm doesn't have a way to express this kind of thing generically, you need to write a specific version for each custom type.

Upvotes: 3

Related Questions