DrBoolean / lenses

Composable kmett style lenses

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Explanation

ccorcos opened this issue · comments

Hey dude, I saw this and wanted to better understand how lenses work. The code was pretty confusing to me, so I thought I'd start with what does this mean?

/*
* type Lens s t a b = ∀f. Functor f => (a -> f b) -> s -> f t
* type Setter s t a b = (a -> Identity b) -> s -> Identity t
* type Getting r s t a b = (a -> Const r b) -> s -> Const r t
* type Getter s a = ∀r. (a -> Const r a) -> s -> Const r s
* type Traversal s t a b = ∀f. Applicative f => (a -> f b) -> s -> f t
* type Fold s a = ∀m. Monoid m => (a -> Const m a) -> s -> Const m s
*/

I have a math background so I understand for-all. But other than that, I'm lost. Any online books or classes you'd recommend?

Hi! I ported the types from this lib/video https://www.youtube.com/watch?v=cefnmjtAolY from edward kmett. I feel like the video is a much better explanation that i could try to type :)

Oy. I'm lost from the very beginning... I don't know Haskell or this notation. Where should I start?

commented

I think this could be a good start. it has lots of ressources. It's a pretty big amount of time to invest, though.

He did the same presentation in scala if that's more familiar. Are you good with functors already? I'd start tbere

I'm pretty much just familiar with JS and Python... I get functors.

commented

@ccorcos the syntax definitely takes some getting used to. Here's how I interpret it:
type Fold s a = ∀m. Monoid m => (a -> Const m a) -> s -> Const m s means
type Fold "I'm defining Fold to be of the type"
s a = "that takes an s and an a"
∀m. Monoid m => "such that for all Monoids m*"
(a -> Const m a) -> "given a function taking an a and returning a Const a m"
s -> "and given an s"
Const m s "Fold will return a Const m s."

* not sure this interpretation is accurate enough.

interesting. that makes sense. the periods we're throwing me off in terms of how it flows. Its also interesting how its all automatically curried in some sense.

So you can read these sentences and understand whats going on without thinking about it for 10 minutes?

Lens s t a b = ∀f. Functor f => (a -> f b) -> s -> f t

I'm not sure this makes much sense to me.

For any functor, a lens takes a function (a -> f b) and an s and return f t. This is meaningless to me. How do I interpret what this function will actually do for me?

Start with the simpler version:

Lens' s a = Lens s s a a

or

Lens' s a = ∀f. Functor f => (a -> f a) -> s -> f s

With the example of a Person with a Name: Lens' Person Name.

Which could be read as:

  • (Name -> f Name) -> if you can transform a Name with some effects from f
  • Person -> f Person then you can transform a person under the same effects

With the use of a Lens, functions will select a specific f to use based on what they want to achieve.

If f = Const Name then we have: (Name -> Const Name Name) -> Person -> Const Name Person. This the lets you extract the Name from a Person - related to the function view.

If f = Identity then we have: (Name -> Identity Name) -> Person -> Identity Person. Which essentially gives you "modify a person's name by some function" - related to the function over.

The full version of Lens adds to this the ability to change types. For example: Lens (l, r) (l, n) r n says we if we can convert an r into an n, then we can transform a pair (l, r) into (l, n).

Does that make sense?

hmm. I think what confuses me is there's no distriction between multiple inputs, multiple outputs, and applying a functor to some arguments.

Lens'  (s, a) = ∀f. Functor f => (a -> f(a)) -> s -> f(s)

Is that the right idea? that f isnt being returned but transforming the arugments? that doesnt seem quite right though.