    {-| Lenses for getters and updates that can potentially fail with some error
    value. Like partial lenses, failing lenses are useful for creating accessor
    labels for multi constructor data types where projection and modification of
    fields will not always succeed. The error value can be used to report what
    caused the failure.
    -}

    {-# LANGUAGE TypeOperators, TupleSections #-}

    module Data.Label.Failing
    ( Lens
    , Failing
    , lens
    , get
    , modify
    , set
    , embed

    -- * Seemingly total modifications.
    , set'
    , modify'
    )
    where

    import Control.Applicative
    import Control.Arrow
    import Control.Category
    import Data.Label.Point (Failing)
    import Prelude hiding ((.), id)

    import qualified Data.Label.Poly as Poly

    {-# INLINE lens    #-}
    {-# INLINE get     #-}
    {-# INLINE modify  #-}
    {-# INLINE set     #-}
    {-# INLINE embed   #-}
    {-# INLINE set'    #-}
    {-# INLINE modify' #-}

    -- | Lens type for situations in which the accessor functions can fail with
    -- some error information.

    type Lens e f o = Poly.Lens (Failing e) f o

    -------------------------------------------------------------------------------

    -- | Create a lens that can fail from a getter and a modifier that can
    -- themselves potentially fail.

    lens :: (f -> Either e o)                       -- ^ Getter.
         -> ((o -> Either e i) -> f -> Either e g)  -- ^ Modifier.
         -> Lens e (f -> g) (o -> i)
    lens :: (f -> Either e o)
    -> ((o -> Either e i) -> f -> Either e g)
    -> Lens e (f -> g) (o -> i)
    lens g :: f -> Either e o
    g s :: (o -> Either e i) -> f -> Either e g
    s = Kleisli (Either e) f o
    -> Kleisli (Either e) (Kleisli (Either e) o i, f) g
    -> Lens e (f -> g) (o -> i)
    forall (cat :: * -> * -> *) f o i g.
    cat f o -> cat (cat o i, f) g -> Lens cat (f -> g) (o -> i)
    Poly.lens ((f -> Either e o) -> Kleisli (Either e) f o
    forall (m :: * -> *) a b. (a -> m b) -> Kleisli m a b
    Kleisli f -> Either e o
    g) (((Kleisli (Either e) o i, f) -> Either e g)
    -> Kleisli (Either e) (Kleisli (Either e) o i, f) g
    forall (m :: * -> *) a b. (a -> m b) -> Kleisli m a b
    Kleisli (\(m :: Kleisli (Either e) o i
    m, f :: f
    f) -> (o -> Either e i) -> f -> Either e g
    s (Kleisli (Either e) o i -> o -> Either e i
    forall (m :: * -> *) a b. Kleisli m a b -> a -> m b
    runKleisli Kleisli (Either e) o i
    m) f
    f))

    -- | Getter for a lens that can fail. When the field to which the lens points
    -- is not accessible the getter returns 'Nothing'.

    get :: Lens e (f -> g) (o -> i) -> f -> Either e o
    get :: Lens e (f -> g) (o -> i) -> f -> Either e o
    get l :: Lens e (f -> g) (o -> i)
    l = Kleisli (Either e) f o -> f -> Either e o
    forall (m :: * -> *) a b. Kleisli m a b -> a -> m b
    runKleisli (Lens e (f -> g) (o -> i) -> Kleisli (Either e) f o
    forall (cat :: * -> * -> *) f g o i.
    Lens cat (f -> g) (o -> i) -> cat f o
    Poly.get Lens e (f -> g) (o -> i)
    l)

    -- | Modifier for a lens that can fail. When the field to which the lens points
    -- is not accessible this function returns 'Left'.

    modify :: Lens e (f -> g) (o -> i) -> (o -> i) -> f -> Either e g
    modify :: Lens e (f -> g) (o -> i) -> (o -> i) -> f -> Either e g
    modify l :: Lens e (f -> g) (o -> i)
    l m :: o -> i
    m = Kleisli (Either e) f g -> f -> Either e g
    forall (m :: * -> *) a b. Kleisli m a b -> a -> m b
    runKleisli (Lens e (f -> g) (o -> i) -> Failing e (Failing e o i, f) g
    forall (cat :: * -> * -> *) f g o i.
    Lens cat (f -> g) (o -> i) -> cat (cat o i, f) g
    Poly.modify Lens e (f -> g) (o -> i)
    l Failing e (Failing e o i, f) g
    -> Failing e f (Failing e o i, f) -> Kleisli (Either e) f g
    forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . (f -> (Failing e o i, f)) -> Failing e f (Failing e o i, f)
    forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
    arr ((o -> i) -> Failing e o i
    forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
    arr o -> i
    m,))

    -- | Setter for a lens that can fail. When the field to which the lens points
    -- is not accessible this function returns 'Left'.

    set :: Lens e (f -> g) (o -> i) -> i -> f -> Either e g
    set :: Lens e (f -> g) (o -> i) -> i -> f -> Either e g
    set l :: Lens e (f -> g) (o -> i)
    l v :: i
    v = Kleisli (Either e) f g -> f -> Either e g
    forall (m :: * -> *) a b. Kleisli m a b -> a -> m b
    runKleisli (Lens e (f -> g) (o -> i) -> Failing e (i, f) g
    forall (arr :: * -> * -> *) f g o i.
    Arrow arr =>
    Lens arr (f -> g) (o -> i) -> arr (i, f) g
    Poly.set Lens e (f -> g) (o -> i)
    l Failing e (i, f) g -> Failing e f (i, f) -> Kleisli (Either e) f g
    forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . (f -> (i, f)) -> Failing e f (i, f)
    forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
    arr (i
    v,))

    -- | Embed a total lens that points to an `Either` field into a lens that might
    -- fail.

    embed :: Poly.Lens (->) (f -> g) (Either e o -> Either e i) -> Lens e (f -> g) (o -> i)
    embed :: Lens (->) (f -> g) (Either e o -> Either e i)
    -> Lens e (f -> g) (o -> i)
    embed l :: Lens (->) (f -> g) (Either e o -> Either e i)
    l = (f -> Either e o)
    -> ((o -> Either e i) -> f -> Either e g)
    -> Lens e (f -> g) (o -> i)
    forall f e o i g.
    (f -> Either e o)
    -> ((o -> Either e i) -> f -> Either e g)
    -> Lens e (f -> g) (o -> i)
    lens (Lens (->) (f -> g) (Either e o -> Either e i) -> f -> Either e o
    forall (cat :: * -> * -> *) f g o i.
    Lens cat (f -> g) (o -> i) -> cat f o
    Poly.get Lens (->) (f -> g) (Either e o -> Either e i)
    l) (\m :: o -> Either e i
    m f :: f
    f -> g -> o -> g
    forall a b. a -> b -> a
    const (Lens (->) (f -> g) (Either e o -> Either e i)
    -> (Either e o -> Either e i, f) -> g
    forall (cat :: * -> * -> *) f g o i.
    Lens cat (f -> g) (o -> i) -> cat (cat o i, f) g
    Poly.modify Lens (->) (f -> g) (Either e o -> Either e i)
    l ((Either e o -> (o -> Either e i) -> Either e i
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= o -> Either e i
    m), f
    f)) (o -> g) -> Either e o -> Either e g
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lens (->) (f -> g) (Either e o -> Either e i) -> f -> Either e o
    forall (cat :: * -> * -> *) f g o i.
    Lens cat (f -> g) (o -> i) -> cat f o
    Poly.get Lens (->) (f -> g) (Either e o -> Either e i)
    l f
    f)

    -------------------------------------------------------------------------------

    -- | Like 'modify' but return behaves like the identity function when the field
    -- could not be set.

    modify' :: Lens e (f -> f) (o -> o) -> (o -> o) -> f -> f
    modify' :: Lens e (f -> f) (o -> o) -> (o -> o) -> f -> f
    modify' l :: Lens e (f -> f) (o -> o)
    l m :: o -> o
    m f :: f
    f = (e -> f) -> (f -> f) -> Either e f -> f
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either (f -> e -> f
    forall a b. a -> b -> a
    const f
    f) f -> f
    forall k (cat :: k -> k -> *) (a :: k). Category cat => cat a a
    id (Lens e (f -> f) (o -> o) -> (o -> o) -> f -> Either e f
    forall e f g o i.
    Lens e (f -> g) (o -> i) -> (o -> i) -> f -> Either e g
    modify Lens e (f -> f) (o -> o)
    l o -> o
    m f
    f)

    -- | Like 'set' but return behaves like the identity function when the field
    -- could not be set.

    set' :: Lens e (f -> f) (o -> o) -> o -> f -> f
    set' :: Lens e (f -> f) (o -> o) -> o -> f -> f
    set' l :: Lens e (f -> f) (o -> o)
    l v :: o
    v f :: f
    f = (e -> f) -> (f -> f) -> Either e f -> f
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either (f -> e -> f
    forall a b. a -> b -> a
    const f
    f) f -> f
    forall k (cat :: k -> k -> *) (a :: k). Category cat => cat a a
    id (Lens e (f -> f) (o -> o) -> o -> f -> Either e f
    forall e f g o i. Lens e (f -> g) (o -> i) -> i -> f -> Either e g
    set Lens e (f -> f) (o -> o)
    l o
    v f
    f)