Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does elm have haskell like lens or something similar?

Tags:

elm

In haskell I use the lens library. Is there something similar in elm? If I have this elm data structure, how could I add 3 to test.a.b.

test = {
  a = {
    b = 5
  }
 }

In haskell I would write: test & a.b ~% (+3). In haskell I can write makeLenses ''RecordName and automatically generate lenses, does elm have that?

like image 865
michaelmesser Avatar asked Jul 02 '16 15:07

michaelmesser


1 Answers

Sort of. It has the Focus library. It would allow you to say something like:

Focus.update (a => b) ((+) 3) test

...to add three to test.a.b. It has two drawbacks that spring to mind. The first is that you have to create your lenses by hand. This isn't a big deal. For your test record above, to create a lens (or focus) by hand, you first need a getter function, which is trivial:

.a

And then a map function, which can apply a function to a given test:

\f test = { test | a = f test.a }

Now you can combine those two to make a focus:

a =
    Focus.create
        .a
        (\f test = { test | a = f test.a })

Do the same for b:

b =
    Focus.create
        .b
        (\f a = { a | b = f a.b })

And now you can combine these two foci with (a => b) and that lets you make the Focus.update call shown above. So there's a bit of boilerplate, but it's no great hardship, and you can do nested gets/sets/updates to your heart's content.

The bigger limitation is, you can't do prisms. So if there's a Maybe involved in your path, you're blocked. Back to doing the nested update the long-long-longhand way.

Why are there no prisms? Because they need higher kinded types, and Elm doesn't have those. (Yet?)

So the answer's yes & no. You can have something Lens-like, but don't expect the full power of Haskell lenses.

Update: Looks like I was wrong on my last point - Monacle provides Prisms. I didn't think it was possible. I stand corrected!

like image 200
Kris Jenkins Avatar answered Nov 07 '22 14:11

Kris Jenkins