Reputation: 14973
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
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
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