Ari Fordsham
Ari Fordsham

Reputation: 2515

What's the difference between view and use in lens?

What's the difference between

view :: MonadReader s m => Getting a s a -> m a

and

use :: MonadState s m => Getting a s a -> m a

in Control.Lens.Getter?

Upvotes: 2

Views: 417

Answers (2)

duplode
duplode

Reputation: 34398

A lens getter gives us a function from its source to its target:

(^.) :: s -> Getting a s a -> a

flip (^.) :: Getting a s a -> s -> a

Any function can be made into a MonadReader computation, with the argument type of the function as the environment type:

asks :: MonadReader s m => (s -> a) -> m a

That being so, (^.) can be generalised to any MonadReader through asks, giving rise to view:

view :: MonadReader s m => Getting a s a -> m a
view g = asks (\s -> s ^. g)

(The definitions I'm using here aren't literally the ones you will find in the Control.Lens.Getter source, but they are equivalent to them as far as results go.)

In a similar way, any function can be made into a MonadState computation that leaves the state unchanged, with the argument type of the function as the state type:

gets :: MonadState s m => (s -> a) -> m a

Accordingly, (^.) can also be generalised to any MonadState through gets, resulting in use:

use :: MonadReader s m => Getting a s a -> m a
use g = gets (\s -> s ^. g)

From another angle, view and use can be seen as variants of asks and gets, respectively, that take a getter as argument, rather than a function directly.

On a final note about view, functions themselves are instances of MonadReader. That being so, view can be used as a prefix/non-operator version of (^.).

Upvotes: 0

Silvio Mayolo
Silvio Mayolo

Reputation: 70407

Taking a look at the type signatures, view takes a MonadReader (such as ReaderT) and use takes a MonadState (such as StateT). Now, view and use both have the same objective: extract a reasonable value from the thing we're looking at.

MonadReader represents read-only state. We can access the value within using ask. MonadState represents read-write state, which can be retrieved with get. So both view and use query the internal state of the monad given, but view calls ask whereas use calls get. Generally speaking, only one will be applicable to your situation.

A look at the source code for the two functions is not particularly enlightening unless you already understand how lenses are implemented (and if you do, then you probably understand the difference between view and use), so this is a good example of a situation where the type signatures can be much more enlightening than the code itself.

Upvotes: 4

Related Questions