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

This module is home to lens definitions that require
[profunctors](https://hackage.haskell.org/package/profunctors), most notably
'Iso' and 'Prism'. Depending on 'profunctors' is quite the to bear — one
that includes all dependencies of @microlens-platform@. For this reason,
@microlens-pro@ re-exports the entirety of "Lens.Micro.Platform", but
with the profunctor-less definitions hidden and overridden with profunctor'd
definitions from this module.
-}

{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE CPP #-}

#ifndef MIN_VERSION_GLASGOW_HASKELL
#   define MIN_VERSION_GLASGOW_HASKELL(x,y,z,z2) 1
#endif

module Lens.Micro.Pro
    (
    -- * Iso: Losslessly convert between types
    -- $isos-note
      Iso, Iso'
    -- ** Constructing Isos
    , iso
    -- ** Iso Combinators
    , from
    , under
    , non, non'
    -- ** Common Isos
    , _Show
    , strict, lazy
    , enum
    , coerced
    , mapping
    , packed, unpacked
    -- ** Miscellaneous
    , AnIso, AnIso'
    , cloneIso
    , withIso

    -- * Prism: A traversal with zero or one targets
    -- $prisms-note
    , Prism, Prism'
    -- ** Constructing Prisms
    , prism, prism'
    -- ** Prism Combinators
    , nearly
    , only
    -- ** Common Prisms
    , _Left, _Right
    , _Just, _Nothing
    , _Empty
    -- ** Miscellaneous
    , APrism, APrism'
    , clonePrism
    , withPrism

    -- * Review
    , AReview
    , SimpleReview
    , re
    , review
    , (#)
    , unto

    , module Lens.Micro.Platform
    )
    where
--------------------------------------------------------------------------------
import Lens.Micro.Contra
import Lens.Micro.Pro.Type
import Lens.Micro.Pro.Internal
import Control.Monad                (guard)
import Control.Monad.Reader.Class
import Data.Coerce
import Data.Maybe
import Data.Tagged
import Data.Functor.Contravariant
import Data.Functor.Identity
import Data.Bifunctor
import Data.Void
import Data.Profunctor
import Data.Profunctor.Unsafe

#if MIN_VERSION_GLASGOW_HASKELL(8,4,4,0)
import GHC.Exts                     (TYPE)
#endif

-- For re-export hiding conflicting names
import Lens.Micro.Platform hiding
    ( _Left, _Right, _Just, _Nothing, _Show
    , strict, lazy, packed, unpacked, non
    )

-- implement instances
import qualified Data.Text                as Text
import qualified Data.Text.Lazy           as Text.Lazy
import qualified Data.HashMap.Strict      as HashMap.Strict
import qualified Data.Map                 as Map
import qualified Data.Vector              as Vector
--------------------------------------------------------------------------------

{- | This type is used for efficient "deconstruction" of an 'Iso', reifying
the type into a concrete pair of inverse functions. From the user's perspective,
a function with an 'AnIso' as an argument is simply expecting a normal 'Iso'.
-}

type AnIso s t a b = Exchange a b a (Identity b)
                  -> Exchange a b s (Identity t)

-- | Monomorphic 'AnIso'.

type AnIso' s a = AnIso s s a a

-- | This type is used for effecient "deconstruction" of a 'Prism'. From the
-- user's perspective, a function with an 'AnPrism' as an argument is simply
-- expecting a normal 'Prism'.

type APrism s t a b = Market a b a (Identity b) -> Market a b s (Identity t)

-- | Monomorphic 'APrism'.

type APrism' s a = Market a a a (Identity a) -> Market a a s (Identity s)

-- | Convert 'AnIso' to 'Iso'. This is useful when you need to store an
-- isomorphism as a data type inside a container and later reconstitute it as an
-- overloaded function.

cloneIso :: AnIso s t a b -> Iso s t a b
cloneIso :: forall s t a b. AnIso s t a b -> Iso s t a b
cloneIso AnIso s t a b
k = AnIso s t a b
-> ((s -> a) -> (b -> t) -> p a (f b) -> p s (f t))
-> p a (f b)
-> p s (f t)
forall s t a b r. AnIso s t a b -> ((s -> a) -> (b -> t) -> r) -> r
withIso AnIso s t a b
k (((s -> a) -> (b -> t) -> p a (f b) -> p s (f t))
 -> p a (f b) -> p s (f t))
-> ((s -> a) -> (b -> t) -> p a (f b) -> p s (f t))
-> p a (f b)
-> p s (f t)
forall a b. (a -> b) -> a -> b
$ \s -> a
sa b -> t
bt -> (s -> a) -> (b -> t) -> Iso s t a b
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso s -> a
sa b -> t
bt

{-# INLINE cloneIso #-}

{- $isos-note

Isos (or isomorphisms) are lenses that convert a value instead of targeting a
part of it; in other words, inside of every list lives a reversed list, inside
of every strict @Text@ lives a lazy @Text@, and inside of every @(a, b)@ lives a
@(b, a)@. Since an isomorphism doesn't lose any information, it's possible to
/reverse/ it and use it in the opposite direction by using @from@:

@
from :: Iso' s a -> Iso' a s
from :: Iso s t a b -> Iso t s b a
@

Isos are constructed from a pair of inverse functions. For example, assume
lawful instances of 'Show' and 'Read':

@
show . read = id
read . show = id
@

The isomorphisms defined in this module are true lens-compatible isos. Many of
them share names with the lens-__incompatible__ definitions from
[Lens.Micro](https://hackage.haskell.org/package/microlens-0.4.13.1/docs/Lens-Micro.html#g:5)
and
[Lens.Micro.Platform](https://hackage.haskell.org/package/microlens-platform-0.4.3.4/docs/Lens-Micro-Platform.html).
For convenience, we re-export Lens.Micro.Platform, but with non-lens-compatible
isos hidden and replaced with lens-compatbile ones.

-}

-- | Construct an 'Iso' from two inverse functions.

iso :: (s -> a) -> (b -> t) -> Iso s t a b
iso :: forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso s -> a
sa b -> t
bt = (s -> a) -> (f b -> f t) -> p a (f b) -> p s (f t)
forall a b c d. (a -> b) -> (c -> d) -> p b c -> p a d
forall (p :: * -> * -> *) a b c d.
Profunctor p =>
(a -> b) -> (c -> d) -> p b c -> p a d
dimap s -> a
sa ((b -> t) -> f b -> f t
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b -> t
bt)

{-# INLINE iso #-}

-- | Invert an 'Iso'. Should you define any 'Iso's, it's expected that they
-- abide by the following law, essentially saying that inverting an 'Iso' twice
-- yields the same 'Iso' you started with.
--
-- @
-- 'from' ('from' l) ≡ l
-- @

from :: AnIso s t a b -> Iso b a t s
from :: forall s t a b. AnIso s t a b -> Iso b a t s
from AnIso s t a b
l = AnIso s t a b
-> ((s -> a) -> (b -> t) -> p t (f s) -> p b (f a))
-> p t (f s)
-> p b (f a)
forall s t a b r. AnIso s t a b -> ((s -> a) -> (b -> t) -> r) -> r
withIso AnIso s t a b
l (((s -> a) -> (b -> t) -> p t (f s) -> p b (f a))
 -> p t (f s) -> p b (f a))
-> ((s -> a) -> (b -> t) -> p t (f s) -> p b (f a))
-> p t (f s)
-> p b (f a)
forall a b. (a -> b) -> a -> b
$ \s -> a
sa b -> t
bt -> (b -> t) -> (s -> a) -> Iso b a t s
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso b -> t
bt s -> a
sa

{-# INLINE from #-}

{- |
Shorthand for @'Lens.Micro.over' '.' 'from'@, e.g.

@
s & 'over' ('from' l) f ≡ s & 'under' l f
@
-}
under :: AnIso s t a b -> (t -> s) -> b -> a
under :: forall s t a b. AnIso s t a b -> (t -> s) -> b -> a
under AnIso s t a b
k = AnIso s t a b
-> ((s -> a) -> (b -> t) -> (t -> s) -> b -> a)
-> (t -> s)
-> b
-> a
forall s t a b r. AnIso s t a b -> ((s -> a) -> (b -> t) -> r) -> r
withIso AnIso s t a b
k (((s -> a) -> (b -> t) -> (t -> s) -> b -> a)
 -> (t -> s) -> b -> a)
-> ((s -> a) -> (b -> t) -> (t -> s) -> b -> a)
-> (t -> s)
-> b
-> a
forall a b. (a -> b) -> a -> b
$ \ s -> a
sa b -> t
bt t -> s
ts -> s -> a
sa (s -> a) -> (b -> s) -> b -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. t -> s
ts (t -> s) -> (b -> t) -> b -> s
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> t
bt

{-# INLINE under #-}

-- | Extract the two functions, @s -> a@ and one @b -> t@ that characterize an
--   'Iso'.

#if MIN_VERSION_GLASGOW_HASKELL(8,4,4,0)
withIso :: forall s t a b rep (r :: TYPE rep).
             AnIso s t a b -> ((s -> a) -> (b -> t) -> r) -> r
#else
withIso :: AnIso s t a b -> ((s -> a) -> (b -> t) -> r) -> r
#endif
withIso :: forall s t a b r. AnIso s t a b -> ((s -> a) -> (b -> t) -> r) -> r
withIso AnIso s t a b
ai (s -> a) -> (b -> t) -> r
k = case AnIso s t a b
ai ((a -> a) -> (b -> Identity b) -> Exchange a b a (Identity b)
forall a b s t. (s -> a) -> (b -> t) -> Exchange a b s t
Exchange a -> a
forall a. a -> a
id b -> Identity b
forall a. a -> Identity a
Identity) of
    Exchange s -> a
sa b -> Identity t
bt -> (s -> a) -> (b -> t) -> r
k s -> a
sa (Identity t -> t
forall a. Identity a -> a
runIdentity (Identity t -> t) -> (b -> Identity t) -> b -> t
forall a b c (q :: * -> * -> *).
Coercible c b =>
q b c -> (a -> b) -> a -> c
forall (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible c b) =>
q b c -> p a b -> p a c
#. b -> Identity t
bt)

{-# INLINE withIso #-}

{- |
Lawful instances of 'Show' and 'Read' give rise to this isomorphism.

@
>>> 123 & from _Show %~ reverse
321
>>> "123" & _Show %~ (*2)
"246"
@
-}

_Show :: (Read a, Show a) => Iso' String a
_Show :: forall a. (Read a, Show a) => Iso' String a
_Show = (String -> a) -> (a -> String) -> Iso String String a a
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso String -> a
forall a. Read a => String -> a
read a -> String
forall a. Show a => a -> String
show

{-# INLINE _Show #-}

{- |
'enum' is a questionable inclusion, as many (most) 'Enum' instances throw
errors for out-of-bounds integers, but it is occasionally useful when used with
that information in mind. Handle with care!

>>> 97 ^. enum :: Char
'a'
>>> (-1) ^. enum :: Char
*** Exception: Prelude.chr: bad argument: (-1)
>>> [True,False] ^. mapping (from enum)
[1,0]
-}

enum :: (Enum a) => Iso' Int a
enum :: forall a. Enum a => Iso' Int a
enum = (Int -> a) -> (a -> Int) -> Iso Int Int a a
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso Int -> a
forall a. Enum a => Int -> a
toEnum a -> Int
forall a. Enum a => a -> Int
fromEnum

{-# INLINE enum #-}

{- |
'non' lets you “relabel” a 'Maybe' by equating 'Nothing' to an arbitrary value
(which you can choose):

>>> Just 1 ^. non 0 1

>>> Nothing ^. non 0 0

The most useful thing about 'non' is that relabeling also works in other
direction. If you try to 'set' the “forbidden” value, it'll be turned to
'Nothing':

>>> Just 1 & non 0 .~ 0 Nothing

Setting anything else works just fine:

>>> Just 1 & non 0 .~ 5 Just 5

Same happens if you try to modify a value:

>>> Just 1 & non 0 %~ subtract 1 Nothing

>>> Just 1 & non 0 %~ (+ 1) Just 2

'non' is often useful when combined with 'at'. For instance, if you have a map
of songs and their playcounts, it makes sense not to store songs with 0 plays in
the map; 'non' can act as a filter that wouldn't pass such entries.

Decrease playcount of a song to 0, and it'll be gone:

>>> fromList [("Soon",1),("Yesterday",3)] & at "Soon" . non 0 %~ subtract 1
fromList [("Yesterday",3)]

Try to add a song with 0 plays, and it won't be added:

>>> fromList [("Yesterday",3)] & at "Soon" . non 0 .~ 0
fromList [("Yesterday",3)]

But it will be added if you set any other number:

>>> fromList [("Yesterday",3)] & at "Soon" . non 0 .~ 1
fromList [("Soon",1),("Yesterday",3)]

'non' is also useful when working with nested maps. Here a nested map is created
when it's missing:

>>> Map.empty & at "Dez Mona" . non Map.empty . at "Soon" .~ Just 1
fromList [("Dez Mona",fromList [("Soon",1)])]

and here it is deleted when its last entry is deleted (notice that 'non' is used
twice here):

>>> fromList [("Dez Mona",fromList [("Soon",1)])] & at "Dez Mona" . non Map.empty . at "Soon" . non 0 %~ subtract 1
fromList []

To understand the last example better, observe the flow of values in it:

* the map goes into @at \"Dez Mona\"@ * the nested map (wrapped into @Just@)
goes into @non Map.empty@ * @Just@ is unwrapped and the nested map goes into @at
\"Soon\"@ * @Just 1@ is unwrapped by @non 0@

Then the final value – i.e. 1 – is modified by @subtract 1@ and the result
(which is 0) starts flowing backwards:

* @non 0@ sees the 0 and produces a @Nothing@

* @at \"Soon\"@ sees @Nothing@ and deletes the corresponding value from the map

* the resulting empty map is passed to @non Map.empty@, which sees that it's
empty and thus produces @Nothing@

* @at \"Dez Mona\"@ sees @Nothing@ and removes the key from the map
-}

non :: (Eq a) => a -> Iso' (Maybe a) a
non :: forall a. Eq a => a -> Iso' (Maybe a) a
non a
a = APrism' a () -> Iso' (Maybe a) a
forall a. APrism' a () -> Iso' (Maybe a) a
non' (APrism' a () -> Iso' (Maybe a) a)
-> APrism' a () -> Iso' (Maybe a) a
forall a b. (a -> b) -> a -> b
$ a -> Prism' a ()
forall a. Eq a => a -> Prism' a ()
only a
a

{-# INLINE non #-}

{- |
'non', but instead of equality with a value, 'non'' equates 'Nothing' to
anything a 'Prism' of your choice doesn't match.

>>> Just [] & non' _Empty .~ [1,2,3]
Just [1,2,3]
>>> Just [] & non' _Empty .~ []
Nothing

See 'non' for cases this may be useful.
-}

non' :: APrism' a () -> Iso' (Maybe a) a
non' :: forall a. APrism' a () -> Iso' (Maybe a) a
non' APrism' a ()
p = (Maybe a -> a) -> (a -> Maybe a) -> Iso (Maybe a) (Maybe a) a a
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso (a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe a
def) a -> Maybe a
go where
  def :: a
def                           = AReview a () -> () -> a
forall b (m :: * -> *) t. MonadReader b m => AReview t b -> m t
review (APrism' a () -> Prism a a () ()
forall s t a b. APrism s t a b -> Prism s t a b
clonePrism APrism' a ()
p) ()
  go :: a -> Maybe a
go a
b | Getting Any a () -> a -> Bool
forall s a. Getting Any s a -> s -> Bool
has (APrism' a () -> Prism a a () ()
forall s t a b. APrism s t a b -> Prism s t a b
clonePrism APrism' a ()
p) a
b   = Maybe a
forall a. Maybe a
Nothing
       | Bool
otherwise              = a -> Maybe a
forall a. a -> Maybe a
Just a
b

{-# INLINE non' #-}

{- |
Coercible types have the same runtime representation, i.e. they are isomorphic.

>>> (Sum 123 :: Sum Int) ^. coerced :: Int
123
-}

coerced :: forall s t a b. (Coercible s a, Coercible t b) => Iso s t a b
coerced :: forall s t a b. (Coercible s a, Coercible t b) => Iso s t a b
coerced p a (f b)
l = (f b -> f t) -> p a (f b) -> p a (f t)
forall b c a. (b -> c) -> p a b -> p a c
forall (p :: * -> * -> *) b c a.
Profunctor p =>
(b -> c) -> p a b -> p a c
rmap ((b -> t) -> f b -> f t
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b -> t
forall a b. Coercible a b => a -> b
coerce) p a (f b)
l p a (f t) -> (s -> a) -> p s (f t)
forall a b c (q :: * -> * -> *).
Coercible b a =>
p b c -> q a b -> p a c
forall (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible b a) =>
p b c -> q a b -> p a c
.# s -> a
forall a b. Coercible a b => a -> b
coerce

{-# INLINE coerced #-}

{- |
An isomorphism holds when lifted into a functor. For example, if a list contains
a bunch of @a@'s which are each isomorphic to a @b@, the whole list of @a@'s is
isomorphic to a list of @b@'s.

>>> ["1","2","3"] ^. mapping _Show :: [Int]
[1,2,3]
>>> ([1,2,3] :: [Int]) ^. from (mapping _Show)
["1","2","3"]

This also hold across different functors:

>>> let l = mapping @[] @Maybe _Show
>>> :t l
l :: (Read b, Show b) => Iso [String] (Maybe String) [b] (Maybe b)
>>> ["1","2","3"] & l %~ Just . sum
Just "6"
-}

mapping :: (Functor f, Functor g) => AnIso s t a b -> Iso (f s) (g t) (f a) (g b)
mapping :: forall (f :: * -> *) (g :: * -> *) s t a b.
(Functor f, Functor g) =>
AnIso s t a b -> Iso (f s) (g t) (f a) (g b)
mapping AnIso s t a b
k = AnIso s t a b
-> ((s -> a) -> (b -> t) -> p (f a) (f (g b)) -> p (f s) (f (g t)))
-> p (f a) (f (g b))
-> p (f s) (f (g t))
forall s t a b r. AnIso s t a b -> ((s -> a) -> (b -> t) -> r) -> r
withIso AnIso s t a b
k (((s -> a) -> (b -> t) -> p (f a) (f (g b)) -> p (f s) (f (g t)))
 -> p (f a) (f (g b)) -> p (f s) (f (g t)))
-> ((s -> a) -> (b -> t) -> p (f a) (f (g b)) -> p (f s) (f (g t)))
-> p (f a) (f (g b))
-> p (f s) (f (g t))
forall a b. (a -> b) -> a -> b
$ \ s -> a
sa b -> t
bt -> (f s -> f a) -> (g b -> g t) -> Iso (f s) (g t) (f a) (g b)
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso ((s -> a) -> f s -> f a
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap s -> a
sa) ((b -> t) -> g b -> g t
forall a b. (a -> b) -> g a -> g b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b -> t
bt)

{-# INLINE mapping #-}

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


{- $prisms-note

If a 'Lens' views and updates individual components of /product/ types, a
'Prism' views and updates individual components of /sum/ types. For example, you
may want to update the 'Left' field of an 'Either':

>>> Left "salmon" & _Left .~ "orb"
Left "orb"
>>> Right "pudding" & _Left .~ "orb"
Right "pudding"

Also similarly to a 'Lens', you might want to view the 'Left' field. However, it
might not always be there, so we treat it as a traversal with either one or zero
results.

>>> Right "bass" ^? _Left
Nothing
>>> Left "bubbles" ^? _Left
Just "bubbles"

A unique feature of 'Prism's is that they may be flipped around using 're' to
construct the larger structure. Maintaining our example of 'Either', remember
that you can construct the entire 'Either' via the constructor 'Left'.

>>> :t re _Left
re _Left :: Getter b (Either b c)
>>> view (re _Left) "bungo"
Left "bungo"

This @'view' ('re' l)@ idiom isn't the prettiest, so we define @'review' =
'view' . 're'@ as shorthand. 'review' also has an infix synonym, '(#)'.

>>> :t _Just
_Just :: Prism (Maybe a) (Maybe b) a b
>>> review _Just "bilbo"
Just "bilbo"
>>> _Just # "bilbo"
Just "bilbo"

As is the whole point of optics, prisms may of course be composed with other
optics:

@
type Thing = Either (Maybe String) (Maybe (Either [Bool] Int))
thing :: Thing
thing = Right (Just (Left [True,False]))
@
>>> thing & _Right . _Just . _Left . each %~ not
Right (Just (Left [False,True]))

-}

{- |
Generate a 'Prism' out of a constructor and a selector. You may wonder
why the selector function returns an 'Either t a' rather than the more obvious
choice of 'Maybe a'; This is to allow @s@ and @t@ to differ — see 'prism''.

@
_Left = prism Left $ either Right (Left . Right)
@
-}

prism :: (b -> t) -> (s -> Either t a) -> Prism s t a b
prism :: forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism b -> t
bt s -> Either t a
seta = (s -> Either t a)
-> (Either t (f b) -> f t)
-> p (Either t a) (Either t (f b))
-> p s (f t)
forall a b c d. (a -> b) -> (c -> d) -> p b c -> p a d
forall (p :: * -> * -> *) a b c d.
Profunctor p =>
(a -> b) -> (c -> d) -> p b c -> p a d
dimap s -> Either t a
seta ((t -> f t) -> (f b -> f t) -> Either t (f b) -> f t
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either t -> f t
forall a. a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((b -> t) -> f b -> f t
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b -> t
bt)) (p (Either t a) (Either t (f b)) -> p s (f t))
-> (p a (f b) -> p (Either t a) (Either t (f b)))
-> p a (f b)
-> p s (f t)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. p a (f b) -> p (Either t a) (Either t (f b))
forall a b c. p a b -> p (Either c a) (Either c b)
forall (p :: * -> * -> *) a b c.
Choice p =>
p a b -> p (Either c a) (Either c b)
right'

{-# INLINE prism #-}

{- |
Generate a 'Prism' out of a constructor and a selector.

@
_Nothing = prism Left $ either Right (Left . Right)
@
-}

prism' :: (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' :: forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' b -> s
bs s -> Maybe a
sma = (b -> s) -> (s -> Either s a) -> Prism s s a b
forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism b -> s
bs (\s
s -> Either s a -> (a -> Either s a) -> Maybe a -> Either s a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (s -> Either s a
forall a b. a -> Either a b
Left s
s) a -> Either s a
forall a b. b -> Either a b
Right (s -> Maybe a
sma s
s))

{-# INLINE prism' #-}

{- |
Clone a Prism so that you can reuse the same monomorphically typed Prism for
different purposes.

Cloning a 'Prism' is one way to make sure you aren't given something weaker,
such as a 'Traversal' and can be used as a way to pass around lenses that have
to be monomorphic in @f@.
-}

clonePrism :: APrism s t a b -> Prism s t a b
clonePrism :: forall s t a b. APrism s t a b -> Prism s t a b
clonePrism APrism s t a b
k = APrism s t a b
-> ((b -> t) -> (s -> Either t a) -> p a (f b) -> p s (f t))
-> p a (f b)
-> p s (f t)
forall s t a b r.
APrism s t a b -> ((b -> t) -> (s -> Either t a) -> r) -> r
withPrism APrism s t a b
k (((b -> t) -> (s -> Either t a) -> p a (f b) -> p s (f t))
 -> p a (f b) -> p s (f t))
-> ((b -> t) -> (s -> Either t a) -> p a (f b) -> p s (f t))
-> p a (f b)
-> p s (f t)
forall a b. (a -> b) -> a -> b
$ \b -> t
bt s -> Either t a
sta -> (b -> t) -> (s -> Either t a) -> Prism s t a b
forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism b -> t
bt s -> Either t a
sta

{-# INLINE clonePrism #-}

{- |
Convert a 'Prism' into the constructor and selector that characterise it. See:
'prism'.
-}

withPrism :: APrism s t a b -> ((b -> t) -> (s -> Either t a) -> r) -> r
withPrism :: forall s t a b r.
APrism s t a b -> ((b -> t) -> (s -> Either t a) -> r) -> r
withPrism APrism s t a b
k (b -> t) -> (s -> Either t a) -> r
f = case Market a b s (Identity t) -> Market a b s t
forall a b. Coercible a b => a -> b
coerce (APrism s t a b
k ((b -> Identity b)
-> (a -> Either (Identity b) a) -> Market a b a (Identity b)
forall a b s t. (b -> t) -> (s -> Either t a) -> Market a b s t
Market b -> Identity b
forall a. a -> Identity a
Identity a -> Either (Identity b) a
forall a b. b -> Either a b
Right)) of
    Market b -> t
bt s -> Either t a
seta -> (b -> t) -> (s -> Either t a) -> r
f b -> t
bt s -> Either t a
seta

{-# INLINE withPrism #-}

{- |
Focus the 'Just' of a 'Maybe'. This might seem redundant, as:

>>> Just "pikyben" ^? _Just
Just "pikyben"

but '_Just' proves useful when composing with other optics.
-}

_Just :: Prism (Maybe a) (Maybe b) a b
_Just :: forall a b (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p a (f b) -> p (Maybe a) (f (Maybe b))
_Just = (b -> Maybe b)
-> (Maybe a -> Either (Maybe b) a)
-> forall {p :: * -> * -> *} {f :: * -> *}.
   (Choice p, Applicative f) =>
   p a (f b) -> p (Maybe a) (f (Maybe b))
forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism b -> Maybe b
forall a. a -> Maybe a
Just ((Maybe a -> Either (Maybe b) a)
 -> forall {p :: * -> * -> *} {f :: * -> *}.
    (Choice p, Applicative f) =>
    p a (f b) -> p (Maybe a) (f (Maybe b)))
-> (Maybe a -> Either (Maybe b) a)
-> forall {p :: * -> * -> *} {f :: * -> *}.
   (Choice p, Applicative f) =>
   p a (f b) -> p (Maybe a) (f (Maybe b))
forall a b. (a -> b) -> a -> b
$ Either (Maybe b) a
-> (a -> Either (Maybe b) a) -> Maybe a -> Either (Maybe b) a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Maybe b -> Either (Maybe b) a
forall a b. a -> Either a b
Left Maybe b
forall a. Maybe a
Nothing) a -> Either (Maybe b) a
forall a b. b -> Either a b
Right

{-# INLINE _Just #-}

{- |
'_Nothing' focuses the 'Nothing' in a 'Maybe'.

>>> Nothing ^? _Nothing 
Just ()
>>> Just "wassa" ^? _Nothing 
Nothing
>>> 'has' _Nothing (Just "something")
False
-}
_Nothing :: Prism' (Maybe a) ()
_Nothing :: forall a (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p () (f ()) -> p (Maybe a) (f (Maybe a))
_Nothing = (() -> Maybe a)
-> (Maybe a -> Maybe ())
-> forall {p :: * -> * -> *} {f :: * -> *}.
   (Choice p, Applicative f) =>
   p () (f ()) -> p (Maybe a) (f (Maybe a))
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' (Maybe a -> () -> Maybe a
forall a b. a -> b -> a
const Maybe a
forall a. Maybe a
Nothing) ((Maybe a -> Maybe ())
 -> forall {p :: * -> * -> *} {f :: * -> *}.
    (Choice p, Applicative f) =>
    p () (f ()) -> p (Maybe a) (f (Maybe a)))
-> (Maybe a -> Maybe ())
-> forall {p :: * -> * -> *} {f :: * -> *}.
   (Choice p, Applicative f) =>
   p () (f ()) -> p (Maybe a) (f (Maybe a))
forall a b. (a -> b) -> a -> b
$ Maybe () -> (a -> Maybe ()) -> Maybe a -> Maybe ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> Maybe ()
forall a. a -> Maybe a
Just ()) (Maybe () -> a -> Maybe ()
forall a b. a -> b -> a
const Maybe ()
forall a. Maybe a
Nothing)

{-# INLINE _Nothing #-}

{- |
Focus the 'Left' component of an 'Either'

>>> Left "doge" ^? _Left
Just "doge"
>>> Right "soge" ^? _Left
Nothing
>>> review _Left "quoge"
Left "quoge"
-}

_Left :: Prism (Either a c) (Either b c) a b
_Left :: forall a c b (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p a (f b) -> p (Either a c) (f (Either b c))
_Left = (b -> Either b c)
-> (Either a c -> Either (Either b c) a)
-> forall {p :: * -> * -> *} {f :: * -> *}.
   (Choice p, Applicative f) =>
   p a (f b) -> p (Either a c) (f (Either b c))
forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism b -> Either b c
forall a b. a -> Either a b
Left ((Either a c -> Either (Either b c) a)
 -> forall {p :: * -> * -> *} {f :: * -> *}.
    (Choice p, Applicative f) =>
    p a (f b) -> p (Either a c) (f (Either b c)))
-> (Either a c -> Either (Either b c) a)
-> forall {p :: * -> * -> *} {f :: * -> *}.
   (Choice p, Applicative f) =>
   p a (f b) -> p (Either a c) (f (Either b c))
forall a b. (a -> b) -> a -> b
$ (a -> Either (Either b c) a)
-> (c -> Either (Either b c) a)
-> Either a c
-> Either (Either b c) a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either a -> Either (Either b c) a
forall a b. b -> Either a b
Right (Either b c -> Either (Either b c) a
forall a b. a -> Either a b
Left (Either b c -> Either (Either b c) a)
-> (c -> Either b c) -> c -> Either (Either b c) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. c -> Either b c
forall a b. b -> Either a b
Right)

{-# INLINE _Left #-}

{- |
Focus the 'Right' component of an 'Either'

>>> Left "doge" ^? _Right
Nothing
>>> Right "soge" ^? _Right
Just "soge"
>>> review _Right "quoge"
Right "quoge"
-}

_Right :: Prism (Either c a) (Either c b) a b
_Right :: forall c a b (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p a (f b) -> p (Either c a) (f (Either c b))
_Right = (b -> Either c b)
-> (Either c a -> Either (Either c b) a)
-> forall {p :: * -> * -> *} {f :: * -> *}.
   (Choice p, Applicative f) =>
   p a (f b) -> p (Either c a) (f (Either c b))
forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism b -> Either c b
forall a b. b -> Either a b
Right ((Either c a -> Either (Either c b) a)
 -> forall {p :: * -> * -> *} {f :: * -> *}.
    (Choice p, Applicative f) =>
    p a (f b) -> p (Either c a) (f (Either c b)))
-> (Either c a -> Either (Either c b) a)
-> forall {p :: * -> * -> *} {f :: * -> *}.
   (Choice p, Applicative f) =>
   p a (f b) -> p (Either c a) (f (Either c b))
forall a b. (a -> b) -> a -> b
$ (c -> Either (Either c b) a)
-> (a -> Either (Either c b) a)
-> Either c a
-> Either (Either c b) a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Either c b -> Either (Either c b) a
forall a b. a -> Either a b
Left (Either c b -> Either (Either c b) a)
-> (c -> Either c b) -> c -> Either (Either c b) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. c -> Either c b
forall a b. a -> Either a b
Left) a -> Either (Either c b) a
forall a b. b -> Either a b
Right

{-# INLINE _Right #-}

class AsEmpty a where
    {- |
    A prism that matches the empty structure.

    >>> has _Empty []
    True
    -}
    _Empty :: Prism' a ()
    default _Empty :: (Monoid a, Eq a) => Prism' a ()
    _Empty = a -> Prism' a ()
forall a. Eq a => a -> Prism' a ()
only a
forall a. Monoid a => a
mempty
    {-# INLINE _Empty #-}

instance AsEmpty [a] where
    _Empty :: Prism' [a] ()
_Empty = [a] -> ([a] -> Bool) -> Prism' [a] ()
forall a. a -> (a -> Bool) -> Prism' a ()
nearly [] [a] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null
    {-# INLINE _Empty #-}

instance AsEmpty (Map.Map k v) where
    _Empty :: Prism' (Map k v) ()
_Empty = Map k v -> (Map k v -> Bool) -> Prism' (Map k v) ()
forall a. a -> (a -> Bool) -> Prism' a ()
nearly Map k v
forall k a. Map k a
Map.empty Map k v -> Bool
forall k a. Map k a -> Bool
Map.null
    {-# INLINE _Empty #-}

instance AsEmpty (Maybe a) where
    _Empty :: Prism' (Maybe a) ()
_Empty = p () (f ()) -> p (Maybe a) (f (Maybe a))
forall a (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p () (f ()) -> p (Maybe a) (f (Maybe a))
_Nothing
    {-# INLINE _Empty #-}

instance AsEmpty (HashMap.Strict.HashMap k v) where
    _Empty :: Prism' (HashMap k v) ()
_Empty = HashMap k v -> (HashMap k v -> Bool) -> Prism' (HashMap k v) ()
forall a. a -> (a -> Bool) -> Prism' a ()
nearly HashMap k v
forall k v. HashMap k v
HashMap.Strict.empty HashMap k v -> Bool
forall k v. HashMap k v -> Bool
HashMap.Strict.null
    {-# INLINE _Empty #-}

instance AsEmpty (Vector.Vector a) where
    _Empty :: Prism' (Vector a) ()
_Empty = Vector a -> (Vector a -> Bool) -> Prism' (Vector a) ()
forall a. a -> (a -> Bool) -> Prism' a ()
nearly Vector a
forall a. Vector a
Vector.empty Vector a -> Bool
forall a. Vector a -> Bool
Vector.null
    {-# INLINE _Empty #-}

instance AsEmpty Text.Text where
    _Empty :: Prism' Text ()
_Empty = Text -> (Text -> Bool) -> Prism' Text ()
forall a. a -> (a -> Bool) -> Prism' a ()
nearly Text
Text.empty Text -> Bool
Text.null
    {-# INLINE _Empty #-}

instance AsEmpty Text.Lazy.Text where
    _Empty :: Prism' Text ()
_Empty = Text -> (Text -> Bool) -> Prism' Text ()
forall a. a -> (a -> Bool) -> Prism' a ()
nearly Text
Text.Lazy.empty Text -> Bool
Text.Lazy.null
    {-# INLINE _Empty #-}

{- |
A prism that matches equality with a value:

>>> 1 ^? only 2
Nothing
>>> 1 ^? only 1
Just 1
-}

only :: Eq a => a -> Prism' a ()
only :: forall a. Eq a => a -> Prism' a ()
only a
a = (() -> a)
-> (a -> Maybe ())
-> forall {p :: * -> * -> *} {f :: * -> *}.
   (Choice p, Applicative f) =>
   p () (f ()) -> p a (f a)
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' (\() -> a
a) ((a -> Maybe ())
 -> forall {p :: * -> * -> *} {f :: * -> *}.
    (Choice p, Applicative f) =>
    p () (f ()) -> p a (f a))
-> (a -> Maybe ())
-> forall {p :: * -> * -> *} {f :: * -> *}.
   (Choice p, Applicative f) =>
   p () (f ()) -> p a (f a)
forall a b. (a -> b) -> a -> b
$ Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Maybe ()) -> (a -> Bool) -> a -> Maybe ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
==)

{-# INLINE only #-}

{- |
@'nearly' a p@ is a prism that matches "loose equality" with @a@ by assuming @p
x@ is true iff @x ≡ a@.

>>> nearly [] null # ()
[]
>>> [1,2,3,4] ^? nearly [] null
Nothing
-}

nearly :: a -> (a -> Bool) -> Prism' a ()
nearly :: forall a. a -> (a -> Bool) -> Prism' a ()
nearly a
a a -> Bool
p = (() -> a)
-> (a -> Maybe ())
-> forall {p :: * -> * -> *} {f :: * -> *}.
   (Choice p, Applicative f) =>
   p () (f ()) -> p a (f a)
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' (\() -> a
a) ((a -> Maybe ())
 -> forall {p :: * -> * -> *} {f :: * -> *}.
    (Choice p, Applicative f) =>
    p () (f ()) -> p a (f a))
-> (a -> Maybe ())
-> forall {p :: * -> * -> *} {f :: * -> *}.
   (Choice p, Applicative f) =>
   p () (f ()) -> p a (f a)
forall a b. (a -> b) -> a -> b
$ Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Maybe ()) -> (a -> Bool) -> a -> Maybe ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Bool
p

{-# INLINE nearly #-}

{- |
If you see this in a signature for a function, the function is expecting a
Review. This usually means a 'Prism' or an 'Iso'.
-}
type AReview t b = Tagged b (Identity b) -> Tagged t (Identity t)

{- |
[@Review@](https://hackage.haskell.org/package/lens-5.2.3/docs/Control-Lens-Type.html#t:Review),
from lens, is limited form of 'Prism' that can only be used for 're' operations.

Similarly to 'SimpleGetter' from microlens, microlens-pro does not define 'Review' and opts for
a less general 'SimpleReview' in order to avoid a
[distributive](https://hackage.haskell.org/package/distributive-0.6.2.1)
dependency.
-}

type SimpleReview t b = forall p. (Choice p, Bifunctor p)
                     => p b (Identity b) -> p t (Identity t)

{-|
Reverse a 'Prism' or 'Iso' and 'view' it

@
review ≡ view . re
@

@
>>> review _Just "sploink"
Just "sploink"
@

'review' is often used with the function monad, @((->)r)@:

@
review :: AReview t b -> b -> t
@
-}

review :: MonadReader b m => AReview t b -> m t
review :: forall b (m :: * -> *) t. MonadReader b m => AReview t b -> m t
review AReview t b
p = (b -> t) -> m t
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (Identity t -> t
forall a. Identity a -> a
runIdentity (Identity t -> t)
-> (Tagged b (Identity b) -> Identity t)
-> Tagged b (Identity b)
-> t
forall a b c (q :: * -> * -> *).
Coercible c b =>
q b c -> (a -> b) -> a -> c
forall (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible c b) =>
q b c -> p a b -> p a c
#. Tagged t (Identity t) -> Identity t
forall {k} (s :: k) b. Tagged s b -> b
unTagged (Tagged t (Identity t) -> Identity t)
-> AReview t b -> Tagged b (Identity b) -> Identity t
forall a b c (q :: * -> * -> *).
Coercible c b =>
q b c -> (a -> b) -> a -> c
forall (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible c b) =>
q b c -> p a b -> p a c
#. AReview t b
p (Tagged b (Identity b) -> t)
-> (Identity b -> Tagged b (Identity b)) -> Identity b -> t
forall a b c (q :: * -> * -> *).
Coercible b a =>
(b -> c) -> q a b -> a -> c
forall (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible b a) =>
p b c -> q a b -> p a c
.# Identity b -> Tagged b (Identity b)
forall {k} (s :: k) b. b -> Tagged s b
Tagged (Identity b -> t) -> (b -> Identity b) -> b -> t
forall a b c (q :: * -> * -> *).
Coercible b a =>
(b -> c) -> q a b -> a -> c
forall (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible b a) =>
p b c -> q a b -> p a c
.# b -> Identity b
forall a. a -> Identity a
Identity)

{-# INLINE review #-}

{-|
Reverse a 'Prism' or 'Iso' turning it into a getter. 're' is a weaker version of
'from', in that you can't flip it back around after reversing it the first time.

>>> "hello worms" ^. re _Just
Just "hello worms"
-}

re :: AReview t b -> Getter b t
re :: forall t b. AReview t b -> Getter b t
re AReview t b
p = (b -> t) -> Getter b t
forall s a. (s -> a) -> Getter s a
toInternal (Identity t -> t
forall a. Identity a -> a
runIdentity (Identity t -> t)
-> (Tagged b (Identity b) -> Identity t)
-> Tagged b (Identity b)
-> t
forall a b c (q :: * -> * -> *).
Coercible c b =>
q b c -> (a -> b) -> a -> c
forall (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible c b) =>
q b c -> p a b -> p a c
#. Tagged t (Identity t) -> Identity t
forall {k} (s :: k) b. Tagged s b -> b
unTagged (Tagged t (Identity t) -> Identity t)
-> AReview t b -> Tagged b (Identity b) -> Identity t
forall a b c (q :: * -> * -> *).
Coercible c b =>
q b c -> (a -> b) -> a -> c
forall (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible c b) =>
q b c -> p a b -> p a c
#. AReview t b
p (Tagged b (Identity b) -> t)
-> (Identity b -> Tagged b (Identity b)) -> Identity b -> t
forall a b c (q :: * -> * -> *).
Coercible b a =>
(b -> c) -> q a b -> a -> c
forall (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible b a) =>
p b c -> q a b -> p a c
.# Identity b -> Tagged b (Identity b)
forall {k} (s :: k) b. b -> Tagged s b
Tagged (Identity b -> t) -> (b -> Identity b) -> b -> t
forall a b c (q :: * -> * -> *).
Coercible b a =>
(b -> c) -> q a b -> a -> c
forall (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible b a) =>
p b c -> q a b -> p a c
.# b -> Identity b
forall a. a -> Identity a
Identity)

{-# INLINE re #-}

-- | An infix synonym of 'review'
(#) :: AReview t b -> b -> t
# :: forall t b. AReview t b -> b -> t
(#) AReview t b
p = Identity t -> t
forall a. Identity a -> a
runIdentity (Identity t -> t)
-> (Tagged b (Identity b) -> Identity t)
-> Tagged b (Identity b)
-> t
forall a b c (q :: * -> * -> *).
Coercible c b =>
q b c -> (a -> b) -> a -> c
forall (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible c b) =>
q b c -> p a b -> p a c
#. Tagged t (Identity t) -> Identity t
forall {k} (s :: k) b. Tagged s b -> b
unTagged (Tagged t (Identity t) -> Identity t)
-> AReview t b -> Tagged b (Identity b) -> Identity t
forall a b c (q :: * -> * -> *).
Coercible c b =>
q b c -> (a -> b) -> a -> c
forall (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible c b) =>
q b c -> p a b -> p a c
#. AReview t b
p (Tagged b (Identity b) -> t)
-> (Identity b -> Tagged b (Identity b)) -> Identity b -> t
forall a b c (q :: * -> * -> *).
Coercible b a =>
(b -> c) -> q a b -> a -> c
forall (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible b a) =>
p b c -> q a b -> p a c
.# Identity b -> Tagged b (Identity b)
forall {k} (s :: k) b. b -> Tagged s b
Tagged (Identity b -> t) -> (b -> Identity b) -> b -> t
forall a b c (q :: * -> * -> *).
Coercible b a =>
(b -> c) -> q a b -> a -> c
forall (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible b a) =>
p b c -> q a b -> p a c
.# b -> Identity b
forall a. a -> Identity a
Identity

infixr 8 #
{-# INLINE (#) #-}

-- Not exported
-- TODO: `to` is temporarily defined here. This should be in microlens-contra,
-- or better yet, microlens as Contravariant has been in base since at least ghc
-- 8.6.5. This definition isn't perfect either -- the version from lens is:
--
-- to :: (Profunctor p, Contravariant f) => (s -> a) -> Optic' p f s a

toInternal :: (s -> a) -> Getter s a
toInternal :: forall s a. (s -> a) -> Getter s a
toInternal s -> a
k = (s -> a) -> (f a -> f s) -> (a -> f a) -> s -> f s
forall a b c d. (a -> b) -> (c -> d) -> (b -> c) -> a -> d
forall (p :: * -> * -> *) a b c d.
Profunctor p =>
(a -> b) -> (c -> d) -> p b c -> p a d
dimap s -> a
k ((s -> a) -> f a -> f s
forall a' a. (a' -> a) -> f a -> f a'
forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
contramap s -> a
k)

{-# INLINE toInternal #-}

{- |
Construct a 'Review' out of a constructor. Consider this more pleasant type
signature:

@
unto :: (b -> t) -> Review' t b
@

Pardon the actual type signature — microlens defines neither @Optic@ (used in
lens'
[@unto@](https://hackage.haskell.org/package/lens-5.2.3/docs/Control-Lens-Combinators.html#v:unto)) nor @Review'@. Here we simply expand the definition of @Optic@.
-}
unto :: (Profunctor p, Bifunctor p, Functor f)
     => (b -> t)
     -> p a (f b) -> p s (f t)
unto :: forall (p :: * -> * -> *) (f :: * -> *) b t a s.
(Profunctor p, Bifunctor p, Functor f) =>
(b -> t) -> p a (f b) -> p s (f t)
unto b -> t
f = (Void -> s) -> p Void (f t) -> p s (f t)
forall a b c. (a -> b) -> p a c -> p b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first Void -> s
forall a. Void -> a
absurd (p Void (f t) -> p s (f t))
-> (p a (f b) -> p Void (f t)) -> p a (f b) -> p s (f t)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Void -> a) -> p a (f t) -> p Void (f t)
forall a b c. (a -> b) -> p b c -> p a c
forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
lmap Void -> a
forall a. Void -> a
absurd (p a (f t) -> p Void (f t))
-> (p a (f b) -> p a (f t)) -> p a (f b) -> p Void (f t)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (f b -> f t) -> p a (f b) -> p a (f t)
forall b c a. (b -> c) -> p a b -> p a c
forall (p :: * -> * -> *) b c a.
Profunctor p =>
(b -> c) -> p a b -> p a c
rmap ((b -> t) -> f b -> f t
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b -> t
f)

{-# INLINE unto #-}

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

instance IsText [Char] where
    packed :: Iso' String String
packed = p String (f String) -> p String (f String)
forall a. a -> a
id
    unpacked :: Iso' String String
unpacked = p String (f String) -> p String (f String)
forall a. a -> a
id

    {-# INLINE packed #-}
    {-# INLINE unpacked #-}

instance IsText Text.Text where
    packed :: Iso' String Text
packed = (String -> Text) -> (Text -> String) -> Iso' String Text
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso String -> Text
Text.pack Text -> String
Text.unpack
    unpacked :: Iso' Text String
unpacked = (Text -> String) -> (String -> Text) -> Iso' Text String
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso Text -> String
Text.unpack String -> Text
Text.pack

    {-# INLINE packed #-}
    {-# INLINE unpacked #-}

instance IsText Text.Lazy.Text where
    packed :: Iso' String Text
packed = (String -> Text) -> (Text -> String) -> Iso' String Text
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso String -> Text
Text.Lazy.pack Text -> String
Text.Lazy.unpack
    unpacked :: Iso' Text String
unpacked = (Text -> String) -> (String -> Text) -> Iso' Text String
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso Text -> String
Text.Lazy.unpack String -> Text
Text.Lazy.pack

    {-# INLINE packed #-}
    {-# INLINE unpacked #-}