Lens.Micro.Mtl.Internal

microlens-mtl-0.1.10.0: microlens support for Reader/Writer/State from mtl

Copyright | (C) 2013-2016 Edward Kmett, 2015-2016 Artyom
License | BSD-style (see the file LICENSE)
Safe Haskell | Trustworthy
Language | Haskell2010

Lens.Micro.Mtl.Internal

Description

This module lets you define your own instances of `Zoom` and `Magnify`.

The warning from Lens.Micro.Internal applies to this module as well. Don't export functions that have `Zoom` or `Magnify` in their type signatures. If you absolutely need to define an instance (e.g. for internal use), only do it for your own types, because otherwise I might add an instance to one of the microlens packages later and if our instances are different it might lead to subtle bugs.

Synopsis

- type family Zoomed (m :: * -> *) :: * -> * -> *
- class (Zoomed m ~ Zoomed n, MonadState s m, MonadState t n) => Zoom m n s t | m -> s, n -> t, m t -> n, n s -> m where
- type family Magnified (m :: * -> *) :: * -> * -> *
- class (Magnified m ~ Magnified n, MonadReader b m, MonadReader a n) => Magnify m n b a | m -> b, n -> a, m a -> n, n b -> m where

# Documentation

type family Zoomed (m :: * -> *) :: * -> * -> * #

This type family is used by `Zoom` to describe the common effect type.

Instances

type Zoomed (ListT m) # |
type Zoomed (ListT m)
type Zoomed (MaybeT m) # |
type Zoomed (MaybeT m)
type Zoomed (ExceptT e m) # |
type Zoomed (ExceptT e m)
type Zoomed (ErrorT e m) # |
type Zoomed (ErrorT e m)
type Zoomed (StateT s z) # |
type Zoomed (StateT s z)
type Zoomed (StateT s z) # |
type Zoomed (StateT s z)
type Zoomed (WriterT w m) # |
type Zoomed (WriterT w m)
type Zoomed (WriterT w m) # |
type Zoomed (WriterT w m)
type Zoomed (IdentityT * m) # |
type Zoomed (IdentityT * m) = Zoomed m
type Zoomed (ReaderT * e m) # |
type Zoomed (ReaderT * e m) = Zoomed m
type Zoomed (RWST r w s z) # |
type Zoomed (RWST r w s z)
type Zoomed (RWST r w s z) # |
type Zoomed (RWST r w s z)

class (Zoomed m ~ Zoomed n, MonadState s m, MonadState t n) => Zoom m n s t | m -> s, n -> t, m t -> n, n s -> m where #

Minimal complete definition

zoom

Methods

zoom :: LensLike' (Zoomed m c) t s -> m c -> n c infixr 2 #

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 = do
      zoom (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 = do
      zoom (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')]
      ...

Instances

Zoom m n s t => Zoom (ListT m) (ListT n) s t # |
Methods zoom :: LensLike' (Zoomed (ListT m) c) t s -> ListT m c -> ListT n c #
Zoom m n s t => Zoom (MaybeT m) (MaybeT n) s t # |
Methods zoom :: LensLike' (Zoomed (MaybeT m) c) t s -> MaybeT m c -> MaybeT n c #
Zoom m n s t => Zoom (ExceptT e m) (ExceptT e n) s t # |
Methods zoom :: LensLike' (Zoomed (ExceptT e m) c) t s -> ExceptT e m c -> ExceptT e n c #
(Error e, Zoom m n s t) => Zoom (ErrorT e m) (ErrorT e n) s t # |
Methods zoom :: LensLike' (Zoomed (ErrorT e m) c) t s -> ErrorT e m c -> ErrorT e n c #
Monad z => Zoom (StateT s z) (StateT t z) s t # |
Methods zoom :: LensLike' (Zoomed (StateT s z) c) t s -> StateT s z c -> StateT t z c #
Monad z => Zoom (StateT s z) (StateT t z) s t # |
Methods zoom :: LensLike' (Zoomed (StateT s z) c) t s -> StateT s z c -> StateT t z c #
(Monoid w, Zoom m n s t) => Zoom (WriterT w m) (WriterT w n) s t # |
Methods zoom :: LensLike' (Zoomed (WriterT w m) c) t s -> WriterT w m c -> WriterT w n c #
(Monoid w, Zoom m n s t) => Zoom (WriterT w m) (WriterT w n) s t # |
Methods zoom :: LensLike' (Zoomed (WriterT w m) c) t s -> WriterT w m c -> WriterT w n c #
Zoom m n s t => Zoom (IdentityT * m) (IdentityT * n) s t # |
Methods zoom :: LensLike' (Zoomed (IdentityT * m) c) t s -> IdentityT * m c -> IdentityT * n c #
Zoom m n s t => Zoom (ReaderT * e m) (ReaderT * e n) s t # |
Methods zoom :: LensLike' (Zoomed (ReaderT * e m) c) t s -> ReaderT * e m c -> ReaderT * e n c #
(Monoid w, Monad z) => Zoom (RWST r w s z) (RWST r w t z) s t # |
Methods zoom :: LensLike' (Zoomed (RWST r w s z) c) t s -> RWST r w s z c -> RWST r w t z c #
(Monoid w, Monad z) => Zoom (RWST r w s z) (RWST r w t z) s t # |
Methods zoom :: LensLike' (Zoomed (RWST r w s z) c) t s -> RWST r w s z c -> RWST r w t z c #

type family Magnified (m :: * -> *) :: * -> * -> * #

This type family is used by `Magnify` to describe the common effect type.

Instances

type Magnified ((->) b) # |
type Magnified ((->) b) = Const *
type Magnified (IdentityT * m) # |
type Magnified (IdentityT * m) = Magnified m
type Magnified (ReaderT * b m) # |
type Magnified (ReaderT * b m)
type Magnified (RWST a w s m) # |
type Magnified (RWST a w s m)
type Magnified (RWST a w s m) # |
type Magnified (RWST a w s m)

class (Magnified m ~ Magnified n, MonadReader b m, MonadReader a n) => Magnify m n b a | m -> b, n -> a, m a -> n, n b -> m where #

Minimal complete definition

magnify

Methods

magnify :: LensLike' (Magnified m c) a b -> m c -> n c infixr 2 #

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 a
    magnify :: 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)

Instances

Magnify ((->) b) ((->) a) b a # |
Methods magnify :: LensLike' (Magnified ((->) b) c) a b -> (b -> c) -> a -> c #
Magnify m n b a => Magnify (IdentityT * m) (IdentityT * n) b a # |
Methods magnify :: LensLike' (Magnified (IdentityT * m) c) a b -> IdentityT * m c -> IdentityT * n c #
Monad m => Magnify (ReaderT * b m) (ReaderT * a m) b a # |
Methods magnify :: LensLike' (Magnified (ReaderT * b m) c) a b -> ReaderT * b m c -> ReaderT * a m c #
(Monad m, Monoid w) => Magnify (RWST b w s m) (RWST a w s m) b a # |
Methods magnify :: LensLike' (Magnified (RWST b w s m) c) a b -> RWST b w s m c -> RWST a w s m c #
(Monad m, Monoid w) => Magnify (RWST b w s m) (RWST a w s m) b a # |
Methods magnify :: LensLike' (Magnified (RWST b w s m) c) a b -> RWST b w s m c -> RWST a w s m c #