    {-# LANGUAGE CPP #-}
    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE FunctionalDependencies #-}
    {-# LANGUAGE FlexibleContexts #-}
    {-# LANGUAGE FlexibleInstances #-}
    {-# LANGUAGE UndecidableInstances #-}
    {-# LANGUAGE ScopedTypeVariables #-}
    {-# LANGUAGE RankNTypes #-}
    {-# LANGUAGE TypeFamilies #-}
    {-# LANGUAGE KindSignatures #-}
    {-# LANGUAGE Trustworthy #-}
    #if !MIN_VERSION_base(4, 9, 0)
    {-# LANGUAGE DataKinds #-}
    #endif

    -- This is needed because ErrorT is deprecated.
    {-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}

    {- |
    Module      :  Lens.Micro.Mtl.Internal
    Copyright   :  (C) 2013-2016 Edward Kmett, 2015-2016 Artyom Kazak, 2018 Monadfix
    License     :  BSD-style (see the file LICENSE)

    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.
    -}
    module Lens.Micro.Mtl.Internal
    (
      -- * Classes
      Zoomed,
      Zoom(..),
      Magnified,
      Magnify(..),

      -- * Focusing (used for 'Zoom')
      Focusing(..),
      FocusingWith(..),
      FocusingPlus(..),
      FocusingOn(..),
      FocusingMay(..),
      FocusingErr(..),

      -- * Effect (used for 'Magnify')
      Effect(..),
      EffectRWS(..),

      -- * Utilities
      May(..),
      Err(..),
    )
    where

    import Control.Applicative
    #if MIN_VERSION_mtl(2, 3, 0)
    import Control.Monad (liftM, liftM2)
    #else
    #endif
    import Control.Monad.Reader as Reader
    import Control.Monad.State as State
    import Control.Monad.Trans.State.Lazy as Lazy
    import Control.Monad.Trans.State.Strict as Strict
    import Control.Monad.Trans.Writer.Lazy as Lazy
    import Control.Monad.Trans.Writer.Strict as Strict
    import Control.Monad.Trans.RWS.Lazy as Lazy
    import Control.Monad.Trans.RWS.Strict as Strict
    #if !MIN_VERSION_transformers(0, 6, 0)
    import Control.Monad.Trans.Error
    import Control.Monad.Trans.List
    #endif
    import Control.Monad.Trans.Except
    import Control.Monad.Trans.Identity
    import Control.Monad.Trans.Maybe
    -- microlens
    import Lens.Micro
    import Lens.Micro.Internal

    #if __GLASGOW_HASKELL__ < 710
    import Data.Monoid
    #endif

    #if MIN_VERSION_base(4,9,0)
    import Data.Kind (Type)
    #endif

    ------------------------------------------------------------------------------
    -- Zoomed
    ------------------------------------------------------------------------------

    -- | This type family is used by 'Zoom' to describe the common effect type.
    #if MIN_VERSION_base(4,9,0)
    type family Zoomed (m :: Type -> Type) :: Type -> Type -> Type
    #else
    type family Zoomed (m :: * -> *) :: * -> * -> *
    #endif
    type instance Zoomed (Strict.StateT s z) = Focusing z
    type instance Zoomed (Lazy.StateT s z) = Focusing z
    type instance Zoomed (ReaderT e m) = Zoomed m
    type instance Zoomed (IdentityT m) = Zoomed m
    type instance Zoomed (Strict.RWST r w s z) = FocusingWith w z
    type instance Zoomed (Lazy.RWST r w s z) = FocusingWith w z
    type instance Zoomed (Strict.WriterT w m) = FocusingPlus w (Zoomed m)
    type instance Zoomed (Lazy.WriterT w m) = FocusingPlus w (Zoomed m)
    #if !MIN_VERSION_transformers(0, 6, 0)
    type instance Zoomed (ListT m) = FocusingOn [] (Zoomed m)
    type instance Zoomed (ErrorT e m) = FocusingErr e (Zoomed m)
    #endif
    type instance Zoomed (MaybeT m) = FocusingMay (Zoomed m)
    type instance Zoomed (ExceptT e m) = FocusingErr e (Zoomed m)

    ------------------------------------------------------------------------------
    -- Focusing
    ------------------------------------------------------------------------------

    -- | Used by 'Zoom' to 'zoom' into 'Control.Monad.State.StateT'.
    newtype Focusing m s a = Focusing { forall (m :: * -> *) s a. Focusing m s a -> m (s, a)
    unfocusing :: m (s, a) }

    instance Monad m => Functor (Focusing m s) where
      fmap :: forall a b. (a -> b) -> Focusing m s a -> Focusing m s b
    fmap a -> b
    f (Focusing m (s, a)
    m) = m (s, b) -> Focusing m s b
    forall (m :: * -> *) s a. m (s, a) -> Focusing m s a
    Focusing (m (s, b) -> Focusing m s b) -> m (s, b) -> Focusing m s b
    forall a b. (a -> b) -> a -> b
    $ do
         (s
    s, a
    a) <- m (s, a)
    m
         (s, b) -> m (s, b)
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (s
    s, a -> b
    f a
    a)
      {-# INLINE fmap #-}

    instance (Monad m, Monoid s) => Applicative (Focusing m s) where
      pure :: forall a. a -> Focusing m s a
    pure a
    a = m (s, a) -> Focusing m s a
    forall (m :: * -> *) s a. m (s, a) -> Focusing m s a
    Focusing ((s, a) -> m (s, a)
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (s
    forall a. Monoid a => a
    mempty, a
    a))
      {-# INLINE pure #-}
      Focusing m (s, a -> b)
    mf <*> :: forall a b.
    Focusing m s (a -> b) -> Focusing m s a -> Focusing m s b
    <*> Focusing m (s, a)
    ma = m (s, b) -> Focusing m s b
    forall (m :: * -> *) s a. m (s, a) -> Focusing m s a
    Focusing (m (s, b) -> Focusing m s b) -> m (s, b) -> Focusing m s b
    forall a b. (a -> b) -> a -> b
    $ do
        (s
    s, a -> b
    f) <- m (s, a -> b)
    mf
        (s
    s', a
    a) <- m (s, a)
    ma
        (s, b) -> m (s, b)
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (s -> s -> s
    forall a. Monoid a => a -> a -> a
    mappend s
    s s
    s', a -> b
    f a
    a)
      {-# INLINE (<*>) #-}

    ------------------------------------------------------------------------------
    -- FocusingWith
    ------------------------------------------------------------------------------

    -- | Used by 'Zoom' to 'zoom' into 'Control.Monad.RWS.RWST'.
    newtype FocusingWith w m s a = FocusingWith { forall w (m :: * -> *) s a. FocusingWith w m s a -> m (s, a, w)
    unfocusingWith :: m (s, a, w) }

    instance Monad m => Functor (FocusingWith w m s) where
      fmap :: forall a b.
    (a -> b) -> FocusingWith w m s a -> FocusingWith w m s b
    fmap a -> b
    f (FocusingWith m (s, a, w)
    m) = m (s, b, w) -> FocusingWith w m s b
    forall w (m :: * -> *) s a. m (s, a, w) -> FocusingWith w m s a
    FocusingWith (m (s, b, w) -> FocusingWith w m s b)
    -> m (s, b, w) -> FocusingWith w m s b
    forall a b. (a -> b) -> a -> b
    $ do
         (s
    s, a
    a, w
    w) <- m (s, a, w)
    m
         (s, b, w) -> m (s, b, w)
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (s
    s, a -> b
    f a
    a, w
    w)
      {-# INLINE fmap #-}

    instance (Monad m, Monoid s, Monoid w) => Applicative (FocusingWith w m s) where
      pure :: forall a. a -> FocusingWith w m s a
    pure a
    a = m (s, a, w) -> FocusingWith w m s a
    forall w (m :: * -> *) s a. m (s, a, w) -> FocusingWith w m s a
    FocusingWith ((s, a, w) -> m (s, a, w)
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (s
    forall a. Monoid a => a
    mempty, a
    a, w
    forall a. Monoid a => a
    mempty))
      {-# INLINE pure #-}
      FocusingWith m (s, a -> b, w)
    mf <*> :: forall a b.
    FocusingWith w m s (a -> b)
    -> FocusingWith w m s a -> FocusingWith w m s b
    <*> FocusingWith m (s, a, w)
    ma = m (s, b, w) -> FocusingWith w m s b
    forall w (m :: * -> *) s a. m (s, a, w) -> FocusingWith w m s a
    FocusingWith (m (s, b, w) -> FocusingWith w m s b)
    -> m (s, b, w) -> FocusingWith w m s b
    forall a b. (a -> b) -> a -> b
    $ do
        (s
    s, a -> b
    f, w
    w) <- m (s, a -> b, w)
    mf
        (s
    s', a
    a, w
    w') <- m (s, a, w)
    ma
        (s, b, w) -> m (s, b, w)
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (s -> s -> s
    forall a. Monoid a => a -> a -> a
    mappend s
    s s
    s', a -> b
    f a
    a, w -> w -> w
    forall a. Monoid a => a -> a -> a
    mappend w
    w w
    w')
      {-# INLINE (<*>) #-}

    ------------------------------------------------------------------------------
    -- FocusingPlus
    ------------------------------------------------------------------------------

    -- | Used by 'Zoom' to 'zoom' into 'Control.Monad.Writer.WriterT'.
    newtype FocusingPlus w k s a = FocusingPlus { forall w (k :: * -> * -> *) s a. FocusingPlus w k s a -> k (s, w) a
    unfocusingPlus :: k (s, w) a }

    instance Functor (k (s, w)) => Functor (FocusingPlus w k s) where
      fmap :: forall a b.
    (a -> b) -> FocusingPlus w k s a -> FocusingPlus w k s b
    fmap a -> b
    f (FocusingPlus k (s, w) a
    as) = k (s, w) b -> FocusingPlus w k s b
    forall w (k :: * -> * -> *) s a. k (s, w) a -> FocusingPlus w k s a
    FocusingPlus ((a -> b) -> k (s, w) a -> k (s, w) b
    forall a b. (a -> b) -> k (s, w) a -> k (s, w) b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> b
    f k (s, w) a
    as)
      {-# INLINE fmap #-}

    instance Applicative (k (s, w)) => Applicative (FocusingPlus w k s) where
      pure :: forall a. a -> FocusingPlus w k s a
    pure = k (s, w) a -> FocusingPlus w k s a
    forall w (k :: * -> * -> *) s a. k (s, w) a -> FocusingPlus w k s a
    FocusingPlus (k (s, w) a -> FocusingPlus w k s a)
    -> (a -> k (s, w) a) -> a -> FocusingPlus w k s a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> k (s, w) a
    forall a. a -> k (s, w) a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure
      {-# INLINE pure #-}
      FocusingPlus k (s, w) (a -> b)
    kf <*> :: forall a b.
    FocusingPlus w k s (a -> b)
    -> FocusingPlus w k s a -> FocusingPlus w k s b
    <*> FocusingPlus k (s, w) a
    ka = k (s, w) b -> FocusingPlus w k s b
    forall w (k :: * -> * -> *) s a. k (s, w) a -> FocusingPlus w k s a
    FocusingPlus (k (s, w) (a -> b)
    kf k (s, w) (a -> b) -> k (s, w) a -> k (s, w) b
    forall a b. k (s, w) (a -> b) -> k (s, w) a -> k (s, w) b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> k (s, w) a
    ka)
      {-# INLINE (<*>) #-}

    ------------------------------------------------------------------------------
    -- FocusingOn
    ------------------------------------------------------------------------------

    -- | Used by 'Zoom' to 'zoom' into 'Control.Monad.Trans.Maybe.MaybeT' or 'Control.Monad.Trans.List.ListT'.
    newtype FocusingOn f k s a = FocusingOn { forall (f :: * -> *) (k :: * -> * -> *) s a.
    FocusingOn f k s a -> k (f s) a
    unfocusingOn :: k (f s) a }

    instance Functor (k (f s)) => Functor (FocusingOn f k s) where
      fmap :: forall a b. (a -> b) -> FocusingOn f k s a -> FocusingOn f k s b
    fmap a -> b
    f (FocusingOn k (f s) a
    as) = k (f s) b -> FocusingOn f k s b
    forall (f :: * -> *) (k :: * -> * -> *) s a.
    k (f s) a -> FocusingOn f k s a
    FocusingOn ((a -> b) -> k (f s) a -> k (f s) b
    forall a b. (a -> b) -> k (f s) a -> k (f s) b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> b
    f k (f s) a
    as)
      {-# INLINE fmap #-}

    instance Applicative (k (f s)) => Applicative (FocusingOn f k s) where
      pure :: forall a. a -> FocusingOn f k s a
    pure = k (f s) a -> FocusingOn f k s a
    forall (f :: * -> *) (k :: * -> * -> *) s a.
    k (f s) a -> FocusingOn f k s a
    FocusingOn (k (f s) a -> FocusingOn f k s a)
    -> (a -> k (f s) a) -> a -> FocusingOn f k s a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> k (f s) a
    forall a. a -> k (f s) a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure
      {-# INLINE pure #-}
      FocusingOn k (f s) (a -> b)
    kf <*> :: forall a b.
    FocusingOn f k s (a -> b)
    -> FocusingOn f k s a -> FocusingOn f k s b
    <*> FocusingOn k (f s) a
    ka = k (f s) b -> FocusingOn f k s b
    forall (f :: * -> *) (k :: * -> * -> *) s a.
    k (f s) a -> FocusingOn f k s a
    FocusingOn (k (f s) (a -> b)
    kf k (f s) (a -> b) -> k (f s) a -> k (f s) b
    forall a b. k (f s) (a -> b) -> k (f s) a -> k (f s) b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> k (f s) a
    ka)
      {-# INLINE (<*>) #-}

    ------------------------------------------------------------------------------
    -- May
    ------------------------------------------------------------------------------

    -- | Make a 'Monoid' out of 'Maybe' for error handling.
    newtype May a = May { forall a. May a -> Maybe a
    getMay :: Maybe a }

    instance Monoid a => Monoid (May a) where
      mempty :: May a
    mempty = Maybe a -> May a
    forall a. Maybe a -> May a
    May (a -> Maybe a
    forall a. a -> Maybe a
    Just a
    forall a. Monoid a => a
    mempty)
      {-# INLINE mempty #-}
    #if !MIN_VERSION_base(4,11,0)
      May Nothing `mappend` _ = May Nothing
      _ `mappend` May Nothing = May Nothing
      May (Just a) `mappend` May (Just b) = May (Just (mappend a b))
      {-# INLINE mappend #-}
    #else
    instance Semigroup a => Semigroup (May a) where
      May Maybe a
    Nothing <> :: May a -> May a -> May a
    <> May a
    _ = Maybe a -> May a
    forall a. Maybe a -> May a
    May Maybe a
    forall a. Maybe a
    Nothing
      May a
    _ <> May Maybe a
    Nothing = Maybe a -> May a
    forall a. Maybe a -> May a
    May Maybe a
    forall a. Maybe a
    Nothing
      May (Just a
    a) <> May (Just a
    b) = Maybe a -> May a
    forall a. Maybe a -> May a
    May (a -> Maybe a
    forall a. a -> Maybe a
    Just (a
    a a -> a -> a
    forall a. Semigroup a => a -> a -> a
    <> a
    b))
      {-# INLINE (<>) #-}
    #endif

    ------------------------------------------------------------------------------
    -- FocusingMay
    ------------------------------------------------------------------------------

    -- | Used by 'Zoom' to 'zoom' into 'Control.Monad.Error.ErrorT'.
    newtype FocusingMay k s a = FocusingMay { forall (k :: * -> * -> *) s a. FocusingMay k s a -> k (May s) a
    unfocusingMay :: k (May s) a }

    instance Functor (k (May s)) => Functor (FocusingMay k s) where
      fmap :: forall a b. (a -> b) -> FocusingMay k s a -> FocusingMay k s b
    fmap a -> b
    f (FocusingMay k (May s) a
    as) = k (May s) b -> FocusingMay k s b
    forall (k :: * -> * -> *) s a. k (May s) a -> FocusingMay k s a
    FocusingMay ((a -> b) -> k (May s) a -> k (May s) b
    forall a b. (a -> b) -> k (May s) a -> k (May s) b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> b
    f k (May s) a
    as)
      {-# INLINE fmap #-}

    instance Applicative (k (May s)) => Applicative (FocusingMay k s) where
      pure :: forall a. a -> FocusingMay k s a
    pure = k (May s) a -> FocusingMay k s a
    forall (k :: * -> * -> *) s a. k (May s) a -> FocusingMay k s a
    FocusingMay (k (May s) a -> FocusingMay k s a)
    -> (a -> k (May s) a) -> a -> FocusingMay k s a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> k (May s) a
    forall a. a -> k (May s) a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure
      {-# INLINE pure #-}
      FocusingMay k (May s) (a -> b)
    kf <*> :: forall a b.
    FocusingMay k s (a -> b) -> FocusingMay k s a -> FocusingMay k s b
    <*> FocusingMay k (May s) a
    ka = k (May s) b -> FocusingMay k s b
    forall (k :: * -> * -> *) s a. k (May s) a -> FocusingMay k s a
    FocusingMay (k (May s) (a -> b)
    kf k (May s) (a -> b) -> k (May s) a -> k (May s) b
    forall a b. k (May s) (a -> b) -> k (May s) a -> k (May s) b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> k (May s) a
    ka)
      {-# INLINE (<*>) #-}

    ------------------------------------------------------------------------------
    -- Err
    ------------------------------------------------------------------------------

    -- | Make a 'Monoid' out of 'Either' for error handling.
    newtype Err e a = Err { forall e a. Err e a -> Either e a
    getErr :: Either e a }

    instance Monoid a => Monoid (Err e a) where
      mempty :: Err e a
    mempty = Either e a -> Err e a
    forall e a. Either e a -> Err e a
    Err (a -> Either e a
    forall a b. b -> Either a b
    Right a
    forall a. Monoid a => a
    mempty)
      {-# INLINE mempty #-}
    #if !MIN_VERSION_base(4,11,0)
      Err (Left e) `mappend` _ = Err (Left e)
      _ `mappend` Err (Left e) = Err (Left e)
      Err (Right a) `mappend` Err (Right b) = Err (Right (mappend a b))
      {-# INLINE mappend #-}
    #else
    instance Semigroup a => Semigroup (Err e a) where
      Err (Left e
    e) <> :: Err e a -> Err e a -> Err e a
    <> Err e a
    _ = Either e a -> Err e a
    forall e a. Either e a -> Err e a
    Err (e -> Either e a
    forall a b. a -> Either a b
    Left e
    e)
      Err e a
    _ <> Err (Left e
    e) = Either e a -> Err e a
    forall e a. Either e a -> Err e a
    Err (e -> Either e a
    forall a b. a -> Either a b
    Left e
    e)
      Err (Right a
    a) <> Err (Right a
    b) = Either e a -> Err e a
    forall e a. Either e a -> Err e a
    Err (a -> Either e a
    forall a b. b -> Either a b
    Right (a
    a a -> a -> a
    forall a. Semigroup a => a -> a -> a
    <> a
    b))
      {-# INLINE (<>) #-}
    #endif

    ------------------------------------------------------------------------------
    -- FocusingErr
    ------------------------------------------------------------------------------

    -- | Used by 'Zoom' to 'zoom' into 'Control.Monad.Error.ErrorT'.
    newtype FocusingErr e k s a = FocusingErr { forall e (k :: * -> * -> *) s a.
    FocusingErr e k s a -> k (Err e s) a
    unfocusingErr :: k (Err e s) a }

    instance Functor (k (Err e s)) => Functor (FocusingErr e k s) where
      fmap :: forall a b. (a -> b) -> FocusingErr e k s a -> FocusingErr e k s b
    fmap a -> b
    f (FocusingErr k (Err e s) a
    as) = k (Err e s) b -> FocusingErr e k s b
    forall e (k :: * -> * -> *) s a.
    k (Err e s) a -> FocusingErr e k s a
    FocusingErr ((a -> b) -> k (Err e s) a -> k (Err e s) b
    forall a b. (a -> b) -> k (Err e s) a -> k (Err e s) b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> b
    f k (Err e s) a
    as)
      {-# INLINE fmap #-}

    instance Applicative (k (Err e s)) => Applicative (FocusingErr e k s) where
      pure :: forall a. a -> FocusingErr e k s a
    pure = k (Err e s) a -> FocusingErr e k s a
    forall e (k :: * -> * -> *) s a.
    k (Err e s) a -> FocusingErr e k s a
    FocusingErr (k (Err e s) a -> FocusingErr e k s a)
    -> (a -> k (Err e s) a) -> a -> FocusingErr e k s a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> k (Err e s) a
    forall a. a -> k (Err e s) a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure
      {-# INLINE pure #-}
      FocusingErr k (Err e s) (a -> b)
    kf <*> :: forall a b.
    FocusingErr e k s (a -> b)
    -> FocusingErr e k s a -> FocusingErr e k s b
    <*> FocusingErr k (Err e s) a
    ka = k (Err e s) b -> FocusingErr e k s b
    forall e (k :: * -> * -> *) s a.
    k (Err e s) a -> FocusingErr e k s a
    FocusingErr (k (Err e s) (a -> b)
    kf k (Err e s) (a -> b) -> k (Err e s) a -> k (Err e s) b
    forall a b. k (Err e s) (a -> b) -> k (Err e s) a -> k (Err e s) b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> k (Err e s) a
    ka)
      {-# INLINE (<*>) #-}

    ------------------------------------------------------------------------------
    -- Zoom
    ------------------------------------------------------------------------------

    infixr 2 `zoom`

    class (MonadState s m, MonadState t n) => Zoom m n s t | m -> s, n -> t, m t -> n, n s -> m where
      {- |
    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 'Lazy.State' \/ 'Lazy.StateT' or 'Lazy.RWS' \/ 'Lazy.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 <https://github.com/ekmett/lens/issues/316 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 :: 'Lazy.State' Game ()
    moveNE = do
      player.position.x 'Lens.Micro.Mtl.+=' 1
      player.position.y 'Lens.Micro.Mtl.+=' 1
    @

    With 'zoom', you can use @player.position@ to focus just on a part of the state:

    @
    moveNE :: 'Lazy.State' Game ()
    moveNE = do
      'zoom' (player.position) $ do
        x 'Lens.Micro.Mtl.+=' 1
        y 'Lens.Micro.Mtl.+=' 1
    @

    You can just as well use it for retrieving things out of the state:

    @
    getCoords :: 'Lazy.State' Game (Int, Int)
    getCoords = 'zoom' (player.position) ((,) '<$>' 'Lens.Micro.Mtl.use' x '<*>' 'Lens.Micro.Mtl.use' y)
    @

    Or more explicitly:

    @
    getCoords = 'zoom' (player.position) $ do
      x' <- 'Lens.Micro.Mtl.use' x
      y' <- 'Lens.Micro.Mtl.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 :: 'Lazy.State' Game ()
    moveObstaclesNE = do
      'zoom' (obstacles.'each') $ do
        x 'Lens.Micro.Mtl.+=' 1
        y 'Lens.Micro.Mtl.+=' 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' <- 'Lens.Micro.Mtl.use' x
        y' <- 'Lens.Micro.Mtl.use' y
        -- Update them.
        x 'Lens.Micro.Mtl..=' x' + 1
        y 'Lens.Micro.Mtl..=' y' + 1
        -- Return a single-element list with old coordinates.
        return [(x', y')]
      ...
    @

    Finally, you might need to write your own instances of 'Zoom' if you use @newtype@d transformers in your monad stack. This can be done as follows:

    @
    import "Lens.Micro.Mtl.Internal"

    type instance 'Zoomed' (MyStateT s m) = 'Zoomed' (StateT s m)

    instance Monad m =\> 'Zoom' (MyStateT s m) (MyStateT t m) s t where
        'zoom' l (MyStateT m) = MyStateT ('zoom' l m)
    @
      -}
      zoom :: LensLike' (Zoomed m c) t s -> m c -> n c

    instance Monad z => Zoom (Strict.StateT s z) (Strict.StateT t z) s t where
      zoom :: forall c.
    LensLike' (Zoomed (StateT s z) c) t s
    -> StateT s z c -> StateT t z c
    zoom LensLike' (Zoomed (StateT s z) c) t s
    l (Strict.StateT s -> z (c, s)
    m) = (t -> z (c, t)) -> StateT t z c
    forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
    Strict.StateT ((t -> z (c, t)) -> StateT t z c)
    -> (t -> z (c, t)) -> StateT t z c
    forall a b. (a -> b) -> a -> b
    $ Focusing z c t -> z (c, t)
    forall (m :: * -> *) s a. Focusing m s a -> m (s, a)
    unfocusing (Focusing z c t -> z (c, t))
    -> (t -> Focusing z c t) -> t -> z (c, t)
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. LensLike' (Zoomed (StateT s z) c) t s
    l (z (c, s) -> Focusing z c s
    forall (m :: * -> *) s a. m (s, a) -> Focusing m s a
    Focusing (z (c, s) -> Focusing z c s)
    -> (s -> z (c, s)) -> s -> Focusing z c s
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. s -> z (c, s)
    m)
      {-# INLINE zoom #-}

    instance Monad z => Zoom (Lazy.StateT s z) (Lazy.StateT t z) s t where
      zoom :: forall c.
    LensLike' (Zoomed (StateT s z) c) t s
    -> StateT s z c -> StateT t z c
    zoom LensLike' (Zoomed (StateT s z) c) t s
    l (Lazy.StateT s -> z (c, s)
    m) = (t -> z (c, t)) -> StateT t z c
    forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
    Lazy.StateT ((t -> z (c, t)) -> StateT t z c)
    -> (t -> z (c, t)) -> StateT t z c
    forall a b. (a -> b) -> a -> b
    $ Focusing z c t -> z (c, t)
    forall (m :: * -> *) s a. Focusing m s a -> m (s, a)
    unfocusing (Focusing z c t -> z (c, t))
    -> (t -> Focusing z c t) -> t -> z (c, t)
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. LensLike' (Zoomed (StateT s z) c) t s
    l (z (c, s) -> Focusing z c s
    forall (m :: * -> *) s a. m (s, a) -> Focusing m s a
    Focusing (z (c, s) -> Focusing z c s)
    -> (s -> z (c, s)) -> s -> Focusing z c s
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. s -> z (c, s)
    m)
      {-# INLINE zoom #-}

    instance Zoom m n s t => Zoom (ReaderT e m) (ReaderT e n) s t where
      zoom :: forall c.
    LensLike' (Zoomed (ReaderT e m) c) t s
    -> ReaderT e m c -> ReaderT e n c
    zoom LensLike' (Zoomed (ReaderT e m) c) t s
    l (ReaderT e -> m c
    m) = (e -> n c) -> ReaderT e n c
    forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
    ReaderT (LensLike' (Zoomed m c) t s -> m c -> n c
    forall c. LensLike' (Zoomed m c) t s -> m c -> n c
    forall (m :: * -> *) (n :: * -> *) s t c.
    Zoom m n s t =>
    LensLike' (Zoomed m c) t s -> m c -> n c
    zoom LensLike' (Zoomed m c) t s
    LensLike' (Zoomed (ReaderT e m) c) t s
    l (m c -> n c) -> (e -> m c) -> e -> n c
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . e -> m c
    m)
      {-# INLINE zoom #-}

    instance Zoom m n s t => Zoom (IdentityT m) (IdentityT n) s t where
      zoom :: forall c.
    LensLike' (Zoomed (IdentityT m) c) t s
    -> IdentityT m c -> IdentityT n c
    zoom LensLike' (Zoomed (IdentityT m) c) t s
    l (IdentityT m c
    m) = n c -> IdentityT n c
    forall {k} (f :: k -> *) (a :: k). f a -> IdentityT f a
    IdentityT (LensLike' (Zoomed m c) t s -> m c -> n c
    forall c. LensLike' (Zoomed m c) t s -> m c -> n c
    forall (m :: * -> *) (n :: * -> *) s t c.
    Zoom m n s t =>
    LensLike' (Zoomed m c) t s -> m c -> n c
    zoom LensLike' (Zoomed m c) t s
    LensLike' (Zoomed (IdentityT m) c) t s
    l m c
    m)
      {-# INLINE zoom #-}

    instance (Monoid w, Monad z) => Zoom (Strict.RWST r w s z) (Strict.RWST r w t z) s t where
      zoom :: forall c.
    LensLike' (Zoomed (RWST r w s z) c) t s
    -> RWST r w s z c -> RWST r w t z c
    zoom LensLike' (Zoomed (RWST r w s z) c) t s
    l (Strict.RWST r -> s -> z (c, s, w)
    m) = (r -> t -> z (c, t, w)) -> RWST r w t z c
    forall r w s (m :: * -> *) a.
    (r -> s -> m (a, s, w)) -> RWST r w s m a
    Strict.RWST ((r -> t -> z (c, t, w)) -> RWST r w t z c)
    -> (r -> t -> z (c, t, w)) -> RWST r w t z c
    forall a b. (a -> b) -> a -> b
    $ \r
    r -> FocusingWith w z c t -> z (c, t, w)
    forall w (m :: * -> *) s a. FocusingWith w m s a -> m (s, a, w)
    unfocusingWith (FocusingWith w z c t -> z (c, t, w))
    -> (t -> FocusingWith w z c t) -> t -> z (c, t, w)
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. LensLike' (Zoomed (RWST r w s z) c) t s
    l (z (c, s, w) -> FocusingWith w z c s
    forall w (m :: * -> *) s a. m (s, a, w) -> FocusingWith w m s a
    FocusingWith (z (c, s, w) -> FocusingWith w z c s)
    -> (s -> z (c, s, w)) -> s -> FocusingWith w z c s
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. r -> s -> z (c, s, w)
    m r
    r)
      {-# INLINE zoom #-}

    instance (Monoid w, Monad z) => Zoom (Lazy.RWST r w s z) (Lazy.RWST r w t z) s t where
      zoom :: forall c.
    LensLike' (Zoomed (RWST r w s z) c) t s
    -> RWST r w s z c -> RWST r w t z c
    zoom LensLike' (Zoomed (RWST r w s z) c) t s
    l (Lazy.RWST r -> s -> z (c, s, w)
    m) = (r -> t -> z (c, t, w)) -> RWST r w t z c
    forall r w s (m :: * -> *) a.
    (r -> s -> m (a, s, w)) -> RWST r w s m a
    Lazy.RWST ((r -> t -> z (c, t, w)) -> RWST r w t z c)
    -> (r -> t -> z (c, t, w)) -> RWST r w t z c
    forall a b. (a -> b) -> a -> b
    $ \r
    r -> FocusingWith w z c t -> z (c, t, w)
    forall w (m :: * -> *) s a. FocusingWith w m s a -> m (s, a, w)
    unfocusingWith (FocusingWith w z c t -> z (c, t, w))
    -> (t -> FocusingWith w z c t) -> t -> z (c, t, w)
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. LensLike' (Zoomed (RWST r w s z) c) t s
    l (z (c, s, w) -> FocusingWith w z c s
    forall w (m :: * -> *) s a. m (s, a, w) -> FocusingWith w m s a
    FocusingWith (z (c, s, w) -> FocusingWith w z c s)
    -> (s -> z (c, s, w)) -> s -> FocusingWith w z c s
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. r -> s -> z (c, s, w)
    m r
    r)
      {-# INLINE zoom #-}

    instance (Monoid w, Zoom m n s t) => Zoom (Strict.WriterT w m) (Strict.WriterT w n) s t where
      zoom :: forall c.
    LensLike' (Zoomed (WriterT w m) c) t s
    -> WriterT w m c -> WriterT w n c
    zoom LensLike' (Zoomed (WriterT w m) c) t s
    l = n (c, w) -> WriterT w n c
    forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
    Strict.WriterT (n (c, w) -> WriterT w n c)
    -> (WriterT w m c -> n (c, w)) -> WriterT w m c -> WriterT w n c
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . LensLike' (Zoomed m (c, w)) t s -> m (c, w) -> n (c, w)
    forall c. LensLike' (Zoomed m c) t s -> m c -> n c
    forall (m :: * -> *) (n :: * -> *) s t c.
    Zoom m n s t =>
    LensLike' (Zoomed m c) t s -> m c -> n c
    zoom (\s -> Zoomed m (c, w) s
    afb -> FocusingPlus w (Zoomed m) c t -> Zoomed m (c, w) t
    forall w (k :: * -> * -> *) s a. FocusingPlus w k s a -> k (s, w) a
    unfocusingPlus (FocusingPlus w (Zoomed m) c t -> Zoomed m (c, w) t)
    -> (t -> FocusingPlus w (Zoomed m) c t) -> t -> Zoomed m (c, w) t
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. LensLike' (Zoomed (WriterT w m) c) t s
    l (Zoomed m (c, w) s -> FocusingPlus w (Zoomed m) c s
    forall w (k :: * -> * -> *) s a. k (s, w) a -> FocusingPlus w k s a
    FocusingPlus (Zoomed m (c, w) s -> FocusingPlus w (Zoomed m) c s)
    -> (s -> Zoomed m (c, w) s) -> s -> FocusingPlus w (Zoomed m) c s
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. s -> Zoomed m (c, w) s
    afb)) (m (c, w) -> n (c, w))
    -> (WriterT w m c -> m (c, w)) -> WriterT w m c -> n (c, w)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . WriterT w m c -> m (c, w)
    forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
    Strict.runWriterT
      {-# INLINE zoom #-}

    instance (Monoid w, Zoom m n s t) => Zoom (Lazy.WriterT w m) (Lazy.WriterT w n) s t where
      zoom :: forall c.
    LensLike' (Zoomed (WriterT w m) c) t s
    -> WriterT w m c -> WriterT w n c
    zoom LensLike' (Zoomed (WriterT w m) c) t s
    l = n (c, w) -> WriterT w n c
    forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
    Lazy.WriterT (n (c, w) -> WriterT w n c)
    -> (WriterT w m c -> n (c, w)) -> WriterT w m c -> WriterT w n c
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . LensLike' (Zoomed m (c, w)) t s -> m (c, w) -> n (c, w)
    forall c. LensLike' (Zoomed m c) t s -> m c -> n c
    forall (m :: * -> *) (n :: * -> *) s t c.
    Zoom m n s t =>
    LensLike' (Zoomed m c) t s -> m c -> n c
    zoom (\s -> Zoomed m (c, w) s
    afb -> FocusingPlus w (Zoomed m) c t -> Zoomed m (c, w) t
    forall w (k :: * -> * -> *) s a. FocusingPlus w k s a -> k (s, w) a
    unfocusingPlus (FocusingPlus w (Zoomed m) c t -> Zoomed m (c, w) t)
    -> (t -> FocusingPlus w (Zoomed m) c t) -> t -> Zoomed m (c, w) t
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. LensLike' (Zoomed (WriterT w m) c) t s
    l (Zoomed m (c, w) s -> FocusingPlus w (Zoomed m) c s
    forall w (k :: * -> * -> *) s a. k (s, w) a -> FocusingPlus w k s a
    FocusingPlus (Zoomed m (c, w) s -> FocusingPlus w (Zoomed m) c s)
    -> (s -> Zoomed m (c, w) s) -> s -> FocusingPlus w (Zoomed m) c s
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. s -> Zoomed m (c, w) s
    afb)) (m (c, w) -> n (c, w))
    -> (WriterT w m c -> m (c, w)) -> WriterT w m c -> n (c, w)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . WriterT w m c -> m (c, w)
    forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
    Lazy.runWriterT
      {-# INLINE zoom #-}

    #if !MIN_VERSION_mtl(2, 3, 0) && !MIN_VERSION_transformers(0, 6, 0)
    instance Zoom m n s t => Zoom (ListT m) (ListT n) s t where
      zoom l = ListT . zoom (\afb -> unfocusingOn . l (FocusingOn . afb)) . runListT
      {-# INLINE zoom #-}

    instance (Error e, Zoom m n s t) => Zoom (ErrorT e m) (ErrorT e n) s t where
      zoom l = ErrorT . liftM getErr . zoom (\afb -> unfocusingErr #. l (FocusingErr #. afb)) . liftM Err . runErrorT
      {-# INLINE zoom #-}
    #endif

    instance Zoom m n s t => Zoom (MaybeT m) (MaybeT n) s t where
      zoom :: forall c.
    LensLike' (Zoomed (MaybeT m) c) t s -> MaybeT m c -> MaybeT n c
    zoom LensLike' (Zoomed (MaybeT m) c) t s
    l = n (Maybe c) -> MaybeT n c
    forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
    MaybeT (n (Maybe c) -> MaybeT n c)
    -> (MaybeT m c -> n (Maybe c)) -> MaybeT m c -> MaybeT n c
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (May c -> Maybe c) -> n (May c) -> n (Maybe c)
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM May c -> Maybe c
    forall a. May a -> Maybe a
    getMay (n (May c) -> n (Maybe c))
    -> (MaybeT m c -> n (May c)) -> MaybeT m c -> n (Maybe c)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . LensLike' (Zoomed m (May c)) t s -> m (May c) -> n (May c)
    forall c. LensLike' (Zoomed m c) t s -> m c -> n c
    forall (m :: * -> *) (n :: * -> *) s t c.
    Zoom m n s t =>
    LensLike' (Zoomed m c) t s -> m c -> n c
    zoom (\s -> Zoomed m (May c) s
    afb -> FocusingMay (Zoomed m) c t -> Zoomed m (May c) t
    forall (k :: * -> * -> *) s a. FocusingMay k s a -> k (May s) a
    unfocusingMay (FocusingMay (Zoomed m) c t -> Zoomed m (May c) t)
    -> (t -> FocusingMay (Zoomed m) c t) -> t -> Zoomed m (May c) t
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. LensLike' (Zoomed (MaybeT m) c) t s
    l (Zoomed m (May c) s -> FocusingMay (Zoomed m) c s
    forall (k :: * -> * -> *) s a. k (May s) a -> FocusingMay k s a
    FocusingMay (Zoomed m (May c) s -> FocusingMay (Zoomed m) c s)
    -> (s -> Zoomed m (May c) s) -> s -> FocusingMay (Zoomed m) c s
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. s -> Zoomed m (May c) s
    afb)) (m (May c) -> n (May c))
    -> (MaybeT m c -> m (May c)) -> MaybeT m c -> n (May c)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Maybe c -> May c) -> m (Maybe c) -> m (May c)
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM Maybe c -> May c
    forall a. Maybe a -> May a
    May (m (Maybe c) -> m (May c))
    -> (MaybeT m c -> m (Maybe c)) -> MaybeT m c -> m (May c)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . MaybeT m c -> m (Maybe c)
    forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
    runMaybeT
      {-# INLINE zoom #-}

    instance Zoom m n s t => Zoom (ExceptT e m) (ExceptT e n) s t where
      zoom :: forall c.
    LensLike' (Zoomed (ExceptT e m) c) t s
    -> ExceptT e m c -> ExceptT e n c
    zoom LensLike' (Zoomed (ExceptT e m) c) t s
    l = n (Either e c) -> ExceptT e n c
    forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
    ExceptT (n (Either e c) -> ExceptT e n c)
    -> (ExceptT e m c -> n (Either e c))
    -> ExceptT e m c
    -> ExceptT e n c
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Err e c -> Either e c) -> n (Err e c) -> n (Either e c)
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM Err e c -> Either e c
    forall e a. Err e a -> Either e a
    getErr (n (Err e c) -> n (Either e c))
    -> (ExceptT e m c -> n (Err e c))
    -> ExceptT e m c
    -> n (Either e c)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . LensLike' (Zoomed m (Err e c)) t s -> m (Err e c) -> n (Err e c)
    forall c. LensLike' (Zoomed m c) t s -> m c -> n c
    forall (m :: * -> *) (n :: * -> *) s t c.
    Zoom m n s t =>
    LensLike' (Zoomed m c) t s -> m c -> n c
    zoom (\s -> Zoomed m (Err e c) s
    afb -> FocusingErr e (Zoomed m) c t -> Zoomed m (Err e c) t
    forall e (k :: * -> * -> *) s a.
    FocusingErr e k s a -> k (Err e s) a
    unfocusingErr (FocusingErr e (Zoomed m) c t -> Zoomed m (Err e c) t)
    -> (t -> FocusingErr e (Zoomed m) c t) -> t -> Zoomed m (Err e c) t
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. LensLike' (Zoomed (ExceptT e m) c) t s
    l (Zoomed m (Err e c) s -> FocusingErr e (Zoomed m) c s
    forall e (k :: * -> * -> *) s a.
    k (Err e s) a -> FocusingErr e k s a
    FocusingErr (Zoomed m (Err e c) s -> FocusingErr e (Zoomed m) c s)
    -> (s -> Zoomed m (Err e c) s) -> s -> FocusingErr e (Zoomed m) c s
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. s -> Zoomed m (Err e c) s
    afb)) (m (Err e c) -> n (Err e c))
    -> (ExceptT e m c -> m (Err e c)) -> ExceptT e m c -> n (Err e c)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Either e c -> Err e c) -> m (Either e c) -> m (Err e c)
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM Either e c -> Err e c
    forall e a. Either e a -> Err e a
    Err (m (Either e c) -> m (Err e c))
    -> (ExceptT e m c -> m (Either e c))
    -> ExceptT e m c
    -> m (Err e c)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ExceptT e m c -> m (Either e c)
    forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
    runExceptT
      {-# INLINE zoom #-}

    -- TODO: instance Zoom m m a a => Zoom (ContT r m) (ContT r m) a a where

    ------------------------------------------------------------------------------
    -- Magnified
    ------------------------------------------------------------------------------

    -- | This type family is used by 'Magnify' to describe the common effect type.
    #if MIN_VERSION_base(4,9,0)
    type family Magnified (m :: Type -> Type) :: Type -> Type -> Type
    #else
    type family Magnified (m :: * -> *) :: * -> * -> *
    #endif
    type instance Magnified (ReaderT b m) = Effect m
    type instance Magnified ((->)b) = Const
    type instance Magnified (Strict.RWST a w s m) = EffectRWS w s m
    type instance Magnified (Lazy.RWST a w s m) = EffectRWS w s m
    type instance Magnified (IdentityT m) = Magnified m

    ------------------------------------------------------------------------------
    -- Magnify
    ------------------------------------------------------------------------------

    infixr 2 `magnify`

    class (MonadReader b m, MonadReader a n) => Magnify m n b a | m -> b, n -> a, m a -> n, n b -> m where
      {- |
    This is an equivalent of 'Reader.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).

    @
    'Reader.local'   :: (r -> r)   -> 'Reader.Reader' r a -> 'Reader.Reader' r a
    'magnify' :: Getter r x -> 'Reader.Reader' x a -> 'Reader.Reader' r a
    @

    'magnify' works with 'Reader.Reader' \/ 'Reader.ReaderT', 'Lazy.RWS' \/ 'Lazy.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.Reader' Config String
    getBase = do
      protocol \<- 'Data.Maybe.fromMaybe' \"https\" '<$>' 'Lens.Micro.Mtl.view' (base.protocol)
      path     \<- 'Lens.Micro.Mtl.view' (base.path)
      return (protocol ++ path)
    @

    With 'magnify', we can factor out @base@:

    @
    getBase = 'magnify' base $ do
      protocol \<- 'Data.Maybe.fromMaybe' \"https\" '<$>' 'Lens.Micro.Mtl.view' protocol
      path     \<- 'Lens.Micro.Mtl.view' path
      return (protocol ++ path)
    @

    This concludes the example.

    Finally, you should know writing instances of 'Magnify' for your own types can be done as follows:

    @
    import "Lens.Micro.Mtl.Internal"

    type instance 'Magnified' (MyReaderT r m) = 'Magnified' (ReaderT r m)

    instance Monad m =\> 'Magnify' (MyReaderT r m) (MyReaderT t m) r t where
        'magnify' l (MyReaderT m) = MyReaderT ('magnify' l m)
    @
      -}
      magnify :: LensLike' (Magnified m c) a b -> m c -> n c

    instance Monad m => Magnify (ReaderT b m) (ReaderT a m) b a where
      magnify :: forall c.
    LensLike' (Magnified (ReaderT b m) c) a b
    -> ReaderT b m c -> ReaderT a m c
    magnify LensLike' (Magnified (ReaderT b m) c) a b
    l (ReaderT b -> m c
    m) = (a -> m c) -> ReaderT a m c
    forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
    ReaderT ((a -> m c) -> ReaderT a m c) -> (a -> m c) -> ReaderT a m c
    forall a b. (a -> b) -> a -> b
    $ Effect m c a -> m c
    forall (m :: * -> *) r a. Effect m r a -> m r
    getEffect (Effect m c a -> m c) -> (a -> Effect m c a) -> a -> m c
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. LensLike' (Magnified (ReaderT b m) c) a b
    l (m c -> Effect m c b
    forall (m :: * -> *) r a. m r -> Effect m r a
    Effect (m c -> Effect m c b) -> (b -> m c) -> b -> Effect m c b
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. b -> m c
    m)
      {-# INLINE magnify #-}

    instance Magnify ((->) b) ((->) a) b a where
      magnify :: forall c.
    LensLike' (Magnified ((->) b) c) a b -> (b -> c) -> a -> c
    magnify LensLike' (Magnified ((->) b) c) a b
    l b -> c
    f = (a -> c) -> a -> c
    forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
    Reader.asks (Const c a -> c
    forall {k} a (b :: k). Const a b -> a
    getConst (Const c a -> c) -> (a -> Const c a) -> a -> c
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. LensLike' (Magnified ((->) b) c) a b
    l (c -> Const c b
    forall {k} a (b :: k). a -> Const a b
    Const (c -> Const c b) -> (b -> c) -> b -> Const c b
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. b -> c
    f))
      {-# INLINE magnify #-}

    instance (Monad m, Monoid w) => Magnify (Strict.RWST b w s m) (Strict.RWST a w s m) b a where
      magnify :: forall c.
    LensLike' (Magnified (RWST b w s m) c) a b
    -> RWST b w s m c -> RWST a w s m c
    magnify LensLike' (Magnified (RWST b w s m) c) a b
    l (Strict.RWST b -> s -> m (c, s, w)
    m) = (a -> s -> m (c, s, w)) -> RWST a w s m c
    forall r w s (m :: * -> *) a.
    (r -> s -> m (a, s, w)) -> RWST r w s m a
    Strict.RWST ((a -> s -> m (c, s, w)) -> RWST a w s m c)
    -> (a -> s -> m (c, s, w)) -> RWST a w s m c
    forall a b. (a -> b) -> a -> b
    $ EffectRWS w s m c a -> s -> m (c, s, w)
    forall w st (m :: * -> *) s a.
    EffectRWS w st m s a -> st -> m (s, st, w)
    getEffectRWS (EffectRWS w s m c a -> s -> m (c, s, w))
    -> (a -> EffectRWS w s m c a) -> a -> s -> m (c, s, w)
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. LensLike' (Magnified (RWST b w s m) c) a b
    l ((s -> m (c, s, w)) -> EffectRWS w s m c b
    forall w st (m :: * -> *) s a.
    (st -> m (s, st, w)) -> EffectRWS w st m s a
    EffectRWS ((s -> m (c, s, w)) -> EffectRWS w s m c b)
    -> (b -> s -> m (c, s, w)) -> b -> EffectRWS w s m c b
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. b -> s -> m (c, s, w)
    m)
      {-# INLINE magnify #-}

    instance (Monad m, Monoid w) => Magnify (Lazy.RWST b w s m) (Lazy.RWST a w s m) b a where
      magnify :: forall c.
    LensLike' (Magnified (RWST b w s m) c) a b
    -> RWST b w s m c -> RWST a w s m c
    magnify LensLike' (Magnified (RWST b w s m) c) a b
    l (Lazy.RWST b -> s -> m (c, s, w)
    m) = (a -> s -> m (c, s, w)) -> RWST a w s m c
    forall r w s (m :: * -> *) a.
    (r -> s -> m (a, s, w)) -> RWST r w s m a
    Lazy.RWST ((a -> s -> m (c, s, w)) -> RWST a w s m c)
    -> (a -> s -> m (c, s, w)) -> RWST a w s m c
    forall a b. (a -> b) -> a -> b
    $ EffectRWS w s m c a -> s -> m (c, s, w)
    forall w st (m :: * -> *) s a.
    EffectRWS w st m s a -> st -> m (s, st, w)
    getEffectRWS (EffectRWS w s m c a -> s -> m (c, s, w))
    -> (a -> EffectRWS w s m c a) -> a -> s -> m (c, s, w)
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. LensLike' (Magnified (RWST b w s m) c) a b
    l ((s -> m (c, s, w)) -> EffectRWS w s m c b
    forall w st (m :: * -> *) s a.
    (st -> m (s, st, w)) -> EffectRWS w st m s a
    EffectRWS ((s -> m (c, s, w)) -> EffectRWS w s m c b)
    -> (b -> s -> m (c, s, w)) -> b -> EffectRWS w s m c b
    forall c b a. Coercible c b => (b -> c) -> (a -> b) -> a -> c
    #. b -> s -> m (c, s, w)
    m)
      {-# INLINE magnify #-}

    instance Magnify m n b a => Magnify (IdentityT m) (IdentityT n) b a where
      magnify :: forall c.
    LensLike' (Magnified (IdentityT m) c) a b
    -> IdentityT m c -> IdentityT n c
    magnify LensLike' (Magnified (IdentityT m) c) a b
    l (IdentityT m c
    m) = n c -> IdentityT n c
    forall {k} (f :: k -> *) (a :: k). f a -> IdentityT f a
    IdentityT (LensLike' (Magnified m c) a b -> m c -> n c
    forall c. LensLike' (Magnified m c) a b -> m c -> n c
    forall (m :: * -> *) (n :: * -> *) b a c.
    Magnify m n b a =>
    LensLike' (Magnified m c) a b -> m c -> n c
    magnify LensLike' (Magnified m c) a b
    LensLike' (Magnified (IdentityT m) c) a b
    l m c
    m)
      {-# INLINE magnify #-}

    -----------------------------------------------------------------------------
    --- Effect
    -------------------------------------------------------------------------------

    -- | Wrap a monadic effect with a phantom type argument.
    newtype Effect m r a = Effect { forall (m :: * -> *) r a. Effect m r a -> m r
    getEffect :: m r }
    -- type role Effect representational nominal phantom

    instance Functor (Effect m r) where
      fmap :: forall a b. (a -> b) -> Effect m r a -> Effect m r b
    fmap a -> b
    _ (Effect m r
    m) = m r -> Effect m r b
    forall (m :: * -> *) r a. m r -> Effect m r a
    Effect m r
    m
      {-# INLINE fmap #-}

    instance (Monad m, Monoid r) => Monoid (Effect m r a) where
      mempty :: Effect m r a
    mempty = m r -> Effect m r a
    forall (m :: * -> *) r a. m r -> Effect m r a
    Effect (r -> m r
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return r
    forall a. Monoid a => a
    mempty)
      {-# INLINE mempty #-}
    #if !MIN_VERSION_base(4,11,0)
      Effect ma `mappend` Effect mb = Effect (liftM2 mappend ma mb)
      {-# INLINE mappend #-}
    #else
    instance (Monad m, Semigroup r) => Semigroup (Effect m r a) where
      Effect m r
    ma <> :: Effect m r a -> Effect m r a -> Effect m r a
    <> Effect m r
    mb = m r -> Effect m r a
    forall (m :: * -> *) r a. m r -> Effect m r a
    Effect ((r -> r -> r) -> m r -> m r -> m r
    forall (m :: * -> *) a1 a2 r.
    Monad m =>
    (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
    liftM2 r -> r -> r
    forall a. Semigroup a => a -> a -> a
    (<>) m r
    ma m r
    mb)
      {-# INLINE (<>) #-}
    #endif

    instance (Monad m, Monoid r) => Applicative (Effect m r) where
      pure :: forall a. a -> Effect m r a
    pure a
    _ = m r -> Effect m r a
    forall (m :: * -> *) r a. m r -> Effect m r a
    Effect (r -> m r
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return r
    forall a. Monoid a => a
    mempty)
      {-# INLINE pure #-}
      Effect m r
    ma <*> :: forall a b. Effect m r (a -> b) -> Effect m r a -> Effect m r b
    <*> Effect m r
    mb = m r -> Effect m r b
    forall (m :: * -> *) r a. m r -> Effect m r a
    Effect ((r -> r -> r) -> m r -> m r -> m r
    forall (m :: * -> *) a1 a2 r.
    Monad m =>
    (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
    liftM2 r -> r -> r
    forall a. Monoid a => a -> a -> a
    mappend m r
    ma m r
    mb)
      {-# INLINE (<*>) #-}

    ------------------------------------------------------------------------------
    -- EffectRWS
    ------------------------------------------------------------------------------

    -- | Wrap a monadic effect with a phantom type argument. Used when magnifying 'Control.Monad.RWS.RWST'.
    newtype EffectRWS w st m s a = EffectRWS { forall w st (m :: * -> *) s a.
    EffectRWS w st m s a -> st -> m (s, st, w)
    getEffectRWS :: st -> m (s,st,w) }

    instance Functor (EffectRWS w st m s) where
      fmap :: forall a b.
    (a -> b) -> EffectRWS w st m s a -> EffectRWS w st m s b
    fmap a -> b
    _ (EffectRWS st -> m (s, st, w)
    m) = (st -> m (s, st, w)) -> EffectRWS w st m s b
    forall w st (m :: * -> *) s a.
    (st -> m (s, st, w)) -> EffectRWS w st m s a
    EffectRWS st -> m (s, st, w)
    m
      {-# INLINE fmap #-}

    instance (Monoid s, Monoid w, Monad m) => Applicative (EffectRWS w st m s) where
      pure :: forall a. a -> EffectRWS w st m s a
    pure a
    _ = (st -> m (s, st, w)) -> EffectRWS w st m s a
    forall w st (m :: * -> *) s a.
    (st -> m (s, st, w)) -> EffectRWS w st m s a
    EffectRWS ((st -> m (s, st, w)) -> EffectRWS w st m s a)
    -> (st -> m (s, st, w)) -> EffectRWS w st m s a
    forall a b. (a -> b) -> a -> b
    $ \st
    st -> (s, st, w) -> m (s, st, w)
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (s
    forall a. Monoid a => a
    mempty, st
    st, w
    forall a. Monoid a => a
    mempty)
      {-# INLINE pure #-}
      EffectRWS st -> m (s, st, w)
    m <*> :: forall a b.
    EffectRWS w st m s (a -> b)
    -> EffectRWS w st m s a -> EffectRWS w st m s b
    <*> EffectRWS st -> m (s, st, w)
    n = (st -> m (s, st, w)) -> EffectRWS w st m s b
    forall w st (m :: * -> *) s a.
    (st -> m (s, st, w)) -> EffectRWS w st m s a
    EffectRWS ((st -> m (s, st, w)) -> EffectRWS w st m s b)
    -> (st -> m (s, st, w)) -> EffectRWS w st m s b
    forall a b. (a -> b) -> a -> b
    $ \st
    st -> st -> m (s, st, w)
    m st
    st m (s, st, w) -> ((s, st, w) -> m (s, st, w)) -> m (s, st, w)
    forall a b. m a -> (a -> m b) -> m b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \ (s
    s,st
    t,w
    w) -> st -> m (s, st, w)
    n st
    t m (s, st, w) -> ((s, st, w) -> m (s, st, w)) -> m (s, st, w)
    forall a b. m a -> (a -> m b) -> m b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \ (s
    s',st
    u,w
    w') -> (s, st, w) -> m (s, st, w)
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (s -> s -> s
    forall a. Monoid a => a -> a -> a
    mappend s
    s s
    s', st
    u, w -> w -> w
    forall a. Monoid a => a -> a -> a
    mappend w
    w w
    w')
      {-# INLINE (<*>) #-}