Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.

Add initial lens faq.#313

Open
fisx wants to merge 2 commits into
masterfrom
2016-03-29-mf-lens-faq
Open

Add initial lens faq.#313
fisx wants to merge 2 commits into
masterfrom
2016-03-29-mf-lens-faq

Conversation

@fisx

@fisx fisx commented Mar 29, 2016

Copy link
Copy Markdown
Collaborator

No description provided.

@fisx fisx assigned np Mar 29, 2016
@fisx

fisx commented Mar 29, 2016

Copy link
Copy Markdown
Collaborator Author

not sure about the title of the older question; if somebody has a better idea...

@np: answer and context to first question missing. thanks! (-:

@andorp andorp assigned andorp and unassigned np Mar 30, 2016
@fisx fisx assigned np and unassigned andorp Mar 30, 2016
@np

np commented Apr 6, 2016

Copy link
Copy Markdown
Collaborator

Here are a few hints at using lenses based on examples.

modifyDb_ :: AulaSetter a -> (a -> a) -> AUpdate ()
modifyDb_ l f = AUpdate . ExceptT . fmap Right $ modify (l %~ f)

First there is no need to wrap the AUpdate stack ourself, this works: modifyDb_ l f = modify (l %~ f).

Then instead of modify (l %~ f) one can use l %= f the mnemonic is that ~ is for functional update and = for MonadState updates.

modifyDb :: AulaLens a -> (a -> a) -> AUpdate a
modifyDb l f = AUpdate . ExceptT . fmap Right $ state (\s -> (f $ s ^. l, l %~ f $ s))

The first remark still applies, secondly this kind of update which also returns the computed result is called a «pass-through» update in lens. The symbol for that in lens is <, so:

  • s & l <+~ 1 returns both the new targeted value and the full updated value: (s ^. l + 1, s & l +~ 1).
  • l <+= 1 increments the state by 1 at location l and returns new targeted value: do { x <- view l; l += 1; pure (x + 1) }.

Some more hints:

  • l .~ Just x becomes l ?~ x.
  • l .= Just x becomes l ?= x.
  • l1 %~ (l2 .~ x) becomes l1 . l2 .~ x.
  • l1 %~ (l2 %~ f) becomes l1 . l2 %~ f.
  • l %~ const x becomes l .~ x.
  • s & l .~ x tends to be more readable than l .~ x $ s
  • id .~ x becomes const x
  • id .= x becomes put x
  • id %~ f becomes f
  • id %= f becomes modify f
  • (l .= x) >> pure x becomes l <.= x

@np np assigned fisx and unassigned np Apr 6, 2016
@fisx

fisx commented Apr 6, 2016

Copy link
Copy Markdown
Collaborator Author

also we should make a list of good resources:

  • spj's skills matter talk
  • kmett's boston meetup marathon
  • ...?
  • reading material?

@fisx

fisx commented Apr 8, 2016

Copy link
Copy Markdown
Collaborator Author

questions from #342:

[...]
        <$> ("email"         .: (email & prelens emailAddress %%~ DF.optionalText))
[...]
        "email"         -> pure [TextInput $ email ^. _Just . re emailAddress]
[...]
        <*> ("desc"  .: ((topic ^. topicDesc) & _Markdown %%~ (DF.text . Just)))
[...]

@np

np commented Apr 13, 2016

Copy link
Copy Markdown
Collaborator
("email" .: (email & prelens emailAddress %%~ DF.optionalText))

The prelens function is gone now and there is a comment about it.

"email" -> pure [TextInput $ email ^. _Just . re emailAddress]

The doc for emailAddress addresses that.

("desc"  .: ((topic ^. topicDesc) & _Markdown %%~ (DF.text . Just)))

Let's abstract (topic ^. topicDesc) as s and (DF.text . Just) as f. We get: s & _Markdown %%~ f.
The operator %%~ is like %~ but works with effectful functions (a -> f b). So this is equivalent to unwrapping the Markdown constructor calling f and wrapping the constructor back again.

@fisx

fisx commented Apr 14, 2016

Copy link
Copy Markdown
Collaborator Author

[copied from https://github.com//pull/360#discussion_r59679339]

instead of

maybe "" id pw

you can write:

pw ^. _Just

This works because when ^. is applied to a Prism it goes down to a Fold and get this type: (^.) :: Monoid a => s -> Fold s a -> a. In our case (^.) :: Maybe ST -> Fold (Maybe ST) ST -> ST which means that the monoid instance for ST is doing the work of defaulting to the empty string.

@fisx

fisx commented May 3, 2016

Copy link
Copy Markdown
Collaborator Author

[irc]

14:57 < npou> fisx_: anyOf is like any but instead of working directly on the
                     containers it applies a lens first

@fisx

fisx commented May 3, 2016

Copy link
Copy Markdown
Collaborator Author

[irc]

15:13 < fisx_> npou: is there a type synonym for this?:
15:13 < fisx_> (Monoid (f User), Functor f, Applicative f, Contravariant f) => 
               (ST -> f ST) -> User -> f User
15:52 < npou> fisx_: the good one is called Getting, the trick was to look at 
              the type sig of anyOf, it takes a `Getting Any s a`.
15:54 < npou> so searchee can be either: `Getting Any User ST` or more generally 
              `Monoid r => Getting r User ST`.

@fisx

fisx commented May 3, 2016

Copy link
Copy Markdown
Collaborator Author

[irc]

15:57 < npou> While Fold is defined as `type Fold s a = forall f. (Contravariant f, 
              Applicative f) => (a -> f a) -> s -> f s`, the docs gives a simpler 
              version: `type Fold s a = forall m. Monoid m => Getting m s a`
15:59 < npou> correspondingly Getter is equivalent to `type Getter s a = forall r. 
              Getting r s a`, which means that we know nothing about `r` hence we can't 
              use it as a monoid
16:00 < npou> So Getting is to keep in mind when using lenses with monoids
16:01 < npou> Also often `r` is equal to `a` as in the type of `view :: MonadReader s m 
              => Getting a s a -> m a`
16:02 < npou> or `(^.) :: s -> Getting a s a -> a`
16:02  * npou tries to get a better grasp at Getting by explaining it...
16:04 < npou> the catch is that searchee ought to be a `Fold User ST` following the 
              "definition" of Fold above.

@fisx

fisx commented May 7, 2016

Copy link
Copy Markdown
Collaborator Author

https://en.wikibooks.org/wiki/Haskell/Lenses_and_functional_references#The_scenic_route_to_lenses

@fisx fisx removed their assignment Jul 19, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants