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

Add initial lens faq. #313

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Add initial lens faq. #313

wants to merge 2 commits into from

Conversation

fisx
Copy link
Collaborator

@fisx fisx commented Mar 29, 2016

No description provided.

@fisx fisx assigned np Mar 29, 2016
@fisx
Copy link
Collaborator Author

fisx commented Mar 29, 2016

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
Copy link
Collaborator

np commented Apr 6, 2016

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
Copy link
Collaborator Author

fisx commented Apr 6, 2016

also we should make a list of good resources:

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

@fisx
Copy link
Collaborator Author

fisx commented Apr 8, 2016

questions from #342:

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

@np
Copy link
Collaborator

np commented Apr 13, 2016

("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
Copy link
Collaborator Author

fisx commented Apr 14, 2016

[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
Copy link
Collaborator Author

fisx commented May 3, 2016

[irc]

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

@fisx
Copy link
Collaborator Author

fisx commented May 3, 2016

[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
Copy link
Collaborator Author

fisx commented May 3, 2016

[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
Copy link
Collaborator Author

fisx commented May 7, 2016

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