
Haskell Lenses In Pictures - klrr
http://adit.io/posts/2013-07-22-lenses-in-pictures.html
======
IanCal
Something that might be worth pointing out to folks newer to haskell is this
syntax

    
    
        location.x `over` (+10) $ player1
    

Here, `over` is _not_ a string. This is not stringly typed programming. It
translates to

    
    
        over (location.x) (+ 10) $ player1
    

It's used to take a function that would normally be

    
    
        function_name argument1 argument2
    

and allow you to call it like so

    
    
        argument1 `function_name` argument2
    

so

    
    
        plus 1 2 = 1 `plus` 2
    

There's nothing special you need to do, and it's purely a style thing.
Sometimes it's easier to read.

Edit - fix from DanWaterworth, the . in location.x is (if I understand the
problem correctly) function composition and therefore location.x is location .
x, so my re-ordering possibly changed things more than I thought. The
principle is the same, but I've wrapped location.x in parentheses, just to be
sure. I'm sure someone more well versed in haskell can correct me on this :)

~~~
DanWaterworth
I haven't checked this, but I believe that:

    
    
        over location.x (+ 10) $ player1
    

Would be read as:

    
    
        (over location) . (x (+ 10)) $ player1
    

It looks like what you want is:

    
    
        over (location . x) (+ 10) $ player1

~~~
tome
Yeah that's a slight niggle with Lens using (.). From an "object oriented"
point of view it looks like (.) should have higher precedence than the
function application, but in Haskell it doesn't.

~~~
asdasf
That's why I really dislike the tendency for people to use "foo.bar" with Lens
instead of "foo . bar". I find the lack of spaces makes it really easy for my
brain to slip into OO mode and start forgetting precedence.

~~~
tome
Yeah I'd agree with you there.

------
barrkel
I've used the same idea behind lenses and bijective functions to fairly good
effect as a basis for declarative data binding in a UI framework (actually,
combined AJAX and web server framework).

When your data mappings can be expressed this way, it's easy to get a lot done
with very little work; things like RoR+JS-du-jour look primitive in
comparison.

A potential downside is that you have to warp your thinking a little bit in
order to make them fit the paradigm, and some instinctive imperative
approaches don't work as well.

~~~
boothead
Do you have a link, this sounds extremely interesting.

I've just started reading Adowey's category theory book, it's amazing when you
start to notice the same basic fundamental structures everywhere!

~~~
barrkel
No specific link. My primary interest in the topic is very applied; primarily
in bidirectional data binding expressions mapping data and business objects to
UI controls, possibly over a transport.

A lens is just a pair of (setter, getter). It's a first-class reference that
you can pass around, much like you'd pass around a pointer to a location;
except you can transform it. If you use bijective functions to do the
transformation, you can wrap both the getter and setter, one with the function
and the other with its inverse. These lenses are a little like pipes,
wormholes or ducts that are attached at one end to your model / data layer /
business layer / wherever.

I simply plugged them into the UI, and added some extra control information
for reactive UI updates at the web application server request / response
boundary. The upshot was that the user could poke at the UI, a request would
be sent down effectively addressing that particular lens endpoint, business
logic as necessary would run, and then the minimal UI update would come back
in the response - only lenses whose values had changed would be sent back. The
business logic never had to specifically tell the UI which bits needed to be
refreshed; the bits that needed to be sent were inferred automatically.

I wrote a data-binding language specifically to implement this scheme. It was
called Gravity, in part because it accreted more and more responsibility in
the system :)

------
alipang
Another great writeup on lenses I highly recommend,
[http://www.haskellforall.com/2013/05/program-imperatively-
us...](http://www.haskellforall.com/2013/05/program-imperatively-using-
haskell.html).

------
brandonbloom
Clojure has provided an excellent model for how to do similar operations in a
dynamically typed language with pervasive maps & vectors:

    
    
        (update-in player1 [:location :x] + 10)
    

This works especially nicely with the threading macros. Here's some random
example I'll make up:

    
    
        (-> player1
            (update-in [:location :x] + 10)
            (assoc-in [:inventory 3 :equipped] true))
    

The general idea is that a tree of associative data structures (which include
integer-indexed vectors) can have a path to a location in the tree reified as
normal data. Then, you can run any ordinary function on a deep position in the
tree without any of the applicative functors machinery.

------
sfvisser
Nice writeup.

Although I really like the fact that lenses (from the `lens` package) can be
composed using regular function composition, instead of the more generalized
category composition like `fclabels` uses, I still think it's weird that the
direction of composition is flipped.

I reads more like OO, but a lot less like idiomatic Haskell.

~~~
crntaylor
I also think it's a bit weird to flip direction of composition, but there are
a couple of advantages --

1\. It keeps the "imperative" feel, so that you can write

    
    
        person.address.zipCode
    

rather than

    
    
        zipCode.address.person
    

2\. There's an argument that mathematical functions are "back to front" and
that it would be more natural to write functions left to right, i.e. (x)f
rather than f(x), so that the function composition f.g is "apply f then apply
g" rather than "apply g then apply f" which is where we are at the moment.

~~~
tel
Let's just go ahead and steal (<) and (>) for directional function composition
everywhere. I'd rather just write `lt` and `gt`.

    
    
        x & f > g > h === h < g < f $ x

~~~
tome
We already have (<<<) and (>>>) so you're nearly there :)

~~~
tel
Those always feel comical to use to me. It's like having a 747 landing strip
to help guide a duck in for a safe landing.

~~~
tome
Yes they are rather big :)

------
dangoor
Brian McKenna just released fantasy-lenses which gives you lenses for
JavaScript:

[https://github.com/puffnfresh/fantasy-
lenses](https://github.com/puffnfresh/fantasy-lenses)

~~~
michaelsbradley
Michael Greenberg also published a JavaScript lenses library back in 2007, as
part of his thesis at the University of Pennsylvania:

[http://www.cis.upenn.edu/~mgree/ugrad/lenses/docs/overview-s...](http://www.cis.upenn.edu/~mgree/ugrad/lenses/docs/overview-
summary-lens.js.html)

It's a bit dated now, to be sure, as there have since been many developments
in the field of "bidirectional programming". See, for example, Daniel Wagner's
paper on "Edit Lenses":

[http://dmwit.com/papers/201107EL.pdf](http://dmwit.com/papers/201107EL.pdf)

------
verroq
I still don't get how people can claim that functional programming is
inituative when mutating a nested struct requires a separate package and
metaprogramming hacks.

~~~
Bogdanp
| mutating a nested struct requires a separate package and metaprogramming
hacks.

But it doesn't. And you would have known this if only you had read the fucking
article.

    
    
        data Position = Position { x :: Int, y :: Int }
        data Player = Player { pos :: Position }
        
        moveRight :: Int -> Player -> Player
        moveRight n (Player (Position x y)) = Player (Position (x + n) y)

~~~
fdej
Every time you add a new property to Player, wouldn't you be forced to update
all such functions to pass along the extra properties?

~~~
knome
Nah. Not if you use an appropriate form to extract the desired member while
leaving the rest alone.

    
    
        data Person = Person { name   :: String  ,
                               age    :: Integer ,
                               height :: Integer ,
                               weight :: Integer
                             }
                    deriving (Show)
        
        makeOlder p@(Person { age = current }) increase = p { age = current + increase }
        
        main = let b = (Person { name = "Bob", age = 50, height = 72, weight = 190 })
                   c = b { age = (age b) + 10 }
                   d = makeOlder b 10
               in do
                 putStrLn (show b)
                 putStrLn (show c)
                 putStrLn (show d)
        
        -- ~/test/E$ ./M
        -- Person {name = "Bob", age = 50, height = 72, weight = 190}
        -- Person {name = "Bob", age = 60, height = 72, weight = 190}
        -- Person {name = "Bob", age = 60, height = 72, weight = 190}

------
bittired
I like the cartoons used, but why set the bar high with chunky bacon:

[http://mislav.uniqpath.com/poignant-
guide/](http://mislav.uniqpath.com/poignant-guide/)

[http://mislav.uniqpath.com/poignant-
guide/images/the.foxes-4...](http://mislav.uniqpath.com/poignant-
guide/images/the.foxes-4b.png)

~~~
auvrw
i like the cartoons too, 'cept they reminded me of

learnyouahaskell.com

at first.

when/where did adding frames from movies get popular?

~~~
MatthewPhillips
I think it's a great convention for Haskell to use. Learn You a Haskell uses
it to wonderful effect. Haskell is hard to learn (at least at first). Even for
people with a functional programming background. The cartoons makes it look
like a children's book, which has a psychology effect of making the material
seem easier.

~~~
ams6110
See also: _The Little Lisper_ a.k.a _The Little Schemer_

------
marshray
I like FP as much as the next guy (who dabbles in it out of curiosity). But I
can't get over thinking that the need to invoke _function composition
composition_ for operations which are trivial in other languages suggests that
somewhere we ended up trying to use the wrong tool for the job.

~~~
bonobo
This isn't the first time I got myself wondering "where do people derive these
ideas from?" I need to read and re-read (and perhaps read once again) a post
full of pictures every time someone try to explain me a new concept in
Haskell. And the more it happens the more I'm convinced that this language is
not an everyday tool.

I don't want people to misinterpret me, I decided to learn Haskell and I don't
regret it. But I often feel it's more like trying to cut vegetables with a
katana: it's challenging, it's fun to practice, and surely it's a powerful
tool, but even if I become a master at it I won't accomplish much alone, and I
definetly won't want people trying this next to me.

The thought of a bad programmer trying to look smart while fiddling in my
Haskell code scares me to no end.

~~~
marshray
Like "a bad programmer trying to look smart" is _exactly_ how Haskell makes me
feel!

------
TeeWEE
Haha I see titties (.)(.)

