Copyright | (C) 2013-2016 Edward Kmett 2015-2016 Artyom |
---|---|
License | BSD-style (see the file LICENSE) |
Safe Haskell | Trustworthy |
Language | Haskell2010 |
- view :: MonadReader s m => Getting a s a -> m a
- preview :: MonadReader s m => Getting (First a) s a -> m (Maybe a)
- use :: MonadState s m => Getting a s a -> m a
- preuse :: MonadState s m => Getting (First a) s a -> m (Maybe a)
- zoom :: Zoom m n s t => LensLike' (Zoomed m c) t s -> m c -> n c
- magnify :: Magnify m n b a => LensLike' (Magnified m c) a b -> m c -> n c
- (.=) :: MonadState s m => ASetter s s a b -> b -> m ()
- (%=) :: MonadState s m => ASetter s s a b -> (a -> b) -> m ()
- (+=) :: (MonadState s m, Num a) => ASetter s s a a -> a -> m ()
- (-=) :: (MonadState s m, Num a) => ASetter s s a a -> a -> m ()
- (*=) :: (MonadState s m, Num a) => ASetter s s a a -> a -> m ()
- (//=) :: (MonadState s m, Fractional a) => ASetter s s a a -> a -> m ()
Documentation
view :: MonadReader s m => Getting a s a -> m a Source #
view
is a synonym for (^.
), generalised for MonadReader
(we are able to use it instead of (^.
) since functions are instances of the MonadReader
class):
>>>
view _1 (1, 2)
1
When you're using Reader
for config and your config type has lenses generated for it, most of the time you'll be using view
instead of asks
:
doSomething :: (MonadReader
Config m) => m Int doSomething = do thingy <-view
setting1 -- same as “asks
(^.
setting1)” anotherThingy <-view
setting2 ...
preview :: MonadReader s m => Getting (First a) s a -> m (Maybe a) Source #
preview
is a synonym for (^?
), generalised for MonadReader
(just like view
, which is a synonym for (^.
)).
>>>
preview each [1..5]
Just 1
use :: MonadState s m => Getting a s a -> m a Source #
use
is ('^.) (or view
) which implicitly operates on the state; for instance, if your state is a record containing a field foo
, you can write
x <- use
foo
to extract foo
from the state. In other words, use
is the same as gets
, but for getters instead of functions.
The implementation of use
is straightforward:
use
l =gets
(view
l)
If you need to extract something with a fold or traversal, you need preuse
.
zoom :: Zoom m n s t => LensLike' (Zoomed m c) t s -> m c -> n c Source #
When you're in a state monad, this function lets you operate on a part of your state. For instance, if your state was a record containing a position
field, after zooming position
would become your whole state (and when you modify it, the bigger structure would be modified as well).
(Your State
/ StateT
or RWS
/ RWST
can be anywhere in the stack, but you can't use zoom
with arbitrary MonadState
because it doesn't provide any methods to change the type of the state. See this issue for details.)
For the sake of the example, let's define some types first:
data Position = Position { _x, _y :: Int } data Player = Player { _position :: Position, ... } data Game = Game { _player :: Player, _obstacles :: [Position], ... } concat <$> mapM makeLenses [''Position, ''Player, ''Game]
Now, here's an action that moves the player north-east:
moveNE ::State
Game () moveNE = do player.position.x+=
1 player.position.y+=
1
With zoom
, you can use player.position
to focus just on a part of the state:
moveNE ::State
Game () moveNE = dozoom
(player.position) $ do x+=
1 y+=
1
You can just as well use it for retrieving things out of the state:
getCoords ::State
Game (Int, Int) getCoords =zoom
(player.position) ((,)<$>
use
x<*>
use
y)
Or more explicitly:
getCoords =zoom
(player.position) $ do x' <-use
x y' <-use
y return (x', y')
When you pass a traversal to zoom
, it'll work as a loop. For instance, here we move all obstacles:
moveObstaclesNE ::State
Game () moveObstaclesNE = dozoom
(obstacles.each) $ do x+=
1 y+=
1
If the action returns a result, all results would be combined with <>
– the same way they're combined when ^.
is passed a traversal. In this example, moveObstaclesNE
returns a list of old coordinates of obstacles in addition to moving them:
moveObstaclesNE = do xys <-zoom
(obstacles.each) $ do -- Get old coordinates. x' <-use
x y' <-use
y -- Update them. x.=
x' + 1 y.=
y' + 1 -- Return a single-element list with old coordinates. return [(x', y')] ...
magnify :: Magnify m n b a => LensLike' (Magnified m c) a b -> m c -> n c Source #
This is an equivalent of local
which lets you apply a getter to your environment instead of merely applying a function (and it also lets you change the type of the environment).
local
:: (r -> r) ->Reader
r a ->Reader
r amagnify
:: Getter r x ->Reader
x a ->Reader
r a
magnify
works with Reader
/ ReaderT
, RWS
/ RWST
, and (->)
.
Here's an example of magnify
being used to work with a part of a bigger config. First, the types:
data URL = URL { _protocol :: Maybe String, _path :: String } data Config = Config { _base :: URL, ... } makeLenses ''URL makeLenses ''Config
Now, let's define a function which returns the base url:
getBase ::Reader
Config String getBase = do protocol <-fromMaybe
"https"<$>
view
(base.protocol) path <-view
(base.path) return (protocol ++ path)
With magnify
, we can factor out base
:
getBase =magnify
base $ do protocol <-fromMaybe
"https"<$>
view
protocol path <-view
path return (protocol ++ path)
(.=) :: MonadState s m => ASetter s s a b -> b -> m () infix 4 Source #
Modify state by “assigning” a value to a part of the state.
This is merely (.~
) which works in MonadState
:
l.=
x =modify
(l.~
x)
(%=) :: MonadState s m => ASetter s s a b -> (a -> b) -> m () infix 4 Source #
(//=) :: (MonadState s m, Fractional a) => ASetter s s a a -> a -> m () infix 4 Source #