{-# LANGUAGE CPP #-}
{-# LANGUAGE Rank2Types #-}

#ifdef TRUSTWORTHY
{-# LANGUAGE Trustworthy #-}
#endif

#include "lens-common.h"

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

-- |

-- Module      :  Control.Lens.Prism

-- Copyright   :  (C) 2012-16 Edward Kmett

-- License     :  BSD-style (see the file LICENSE)

-- Maintainer  :  Edward Kmett <ekmett@gmail.com>

-- Stability   :  provisional

-- Portability :  non-portable

--

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

module Control.Lens.Prism
  (
  -- * Prisms

    Prism, Prism'
  , APrism, APrism'
  -- * Constructing Prisms

  , prism
  , prism'
  -- * Consuming Prisms

  , withPrism
  , clonePrism
  , outside
  , aside
  , without
  , below
  , isn't
  , matching
  , matching'
  -- * Common Prisms

  , _Left
  , _Right
  , _Just
  , _Nothing
  , _Void
  , _Show
  , only
  , nearly
  , Prefixed(..)
  , Suffixed(..)
  -- * Prismatic profunctors

  , Choice(..)
  ) where

import Prelude ()

import Control.Applicative
import qualified Control.Lens.Internal.List as List
import Control.Lens.Internal.Prism
import Control.Lens.Internal.Prelude
import Control.Lens.Lens
import Control.Lens.Review
import Control.Lens.Type
import Control.Monad
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BL
import qualified Data.List as List
import Data.Profunctor.Rep
import qualified Data.Text as TS
import qualified Data.Text.Lazy as TL

-- $setup

-- >>> :set -XNoOverloadedStrings

-- >>> import Control.Lens

-- >>> import Numeric.Natural

-- >>> import Debug.SimpleReflect.Expr

-- >>> import Debug.SimpleReflect.Vars as Vars hiding (f,g)

-- >>> let isLeft  (Left  _) = True; isLeft  _ = False

-- >>> let isRight (Right _) = True; isRight _ = False

-- >>> let f :: Expr -> Expr; f = Debug.SimpleReflect.Vars.f

-- >>> let g :: Expr -> Expr; g = Debug.SimpleReflect.Vars.g


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

-- Prism Internals

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


-- | If you see this in a signature for a function, the function is expecting a 'Prism'.

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

-- | @

-- type APrism' = 'Simple' 'APrism'

-- @

type APrism' s a = APrism s s a a

-- | Convert 'APrism' to the pair of functions that characterize it.

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 coerce :: forall a b. Coercible a b => a -> b
coerce (APrism s t a b
k (forall a b s t. (b -> t) -> (s -> Either t a) -> Market a b s t
Market forall a. a -> Identity a
Identity 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 #-}

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

--

-- See 'Control.Lens.Lens.cloneLens' and 'Control.Lens.Traversal.cloneTraversal' for examples of why you might want to do this.

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 = 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 forall a b. (a -> b) -> a -> b
$ \b -> t
bt s -> Either t a
sta -> 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 #-}

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

-- Prism Combinators

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


-- | Build a 'Control.Lens.Prism.Prism'.

--

-- @'Either' t a@ is used instead of @'Maybe' a@ to permit the types of @s@ and @t@ to differ.

--

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 = forall (p :: * -> * -> *) a b c d.
Profunctor p =>
(a -> b) -> (c -> d) -> p b c -> p a d
dimap s -> Either t a
seta (forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b -> t
bt)) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) a b c.
Choice p =>
p a b -> p (Either c a) (Either c b)
right'
{-# INLINE prism #-}

-- | This is usually used to build a 'Prism'', when you have to use an operation like

-- 'Data.Typeable.cast' which already returns a 'Maybe'.

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 = forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism b -> s
bs (\s
s -> forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall a b. a -> Either a b
Left s
s) forall a b. b -> Either a b
Right (s -> Maybe a
sma s
s))
{-# INLINE prism' #-}

-- | Use a 'Prism' as a kind of first-class pattern.

--

-- @'outside' :: 'Prism' s t a b -> 'Lens' (t -> r) (s -> r) (b -> r) (a -> r)@


-- TODO: can we make this work with merely Strong?

outside :: Representable p => APrism s t a b -> Lens (p t r) (p s r) (p b r) (p a r)
outside :: forall (p :: * -> * -> *) s t a b r.
Representable p =>
APrism s t a b -> Lens (p t r) (p s r) (p b r) (p a r)
outside APrism s t a b
k = 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 forall a b. (a -> b) -> a -> b
$ \b -> t
bt s -> Either t a
seta p b r -> f (p a r)
f p t r
ft ->
  p b r -> f (p a r)
f (forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
lmap b -> t
bt p t r
ft) forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \p a r
fa -> forall (p :: * -> * -> *) d c.
Representable p =>
(d -> Rep p c) -> p d c
tabulate forall a b. (a -> b) -> a -> b
$ forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall (p :: * -> * -> *) (f :: * -> *) a b.
Sieve p f =>
p a b -> a -> f b
sieve p t r
ft) (forall (p :: * -> * -> *) (f :: * -> *) a b.
Sieve p f =>
p a b -> a -> f b
sieve p a r
fa) forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> Either t a
seta
{-# INLINE outside #-}

-- | Given a pair of prisms, project sums.

--

-- Viewing a 'Prism' as a co-'Lens', this combinator can be seen to be dual to 'Control.Lens.Lens.alongside'.

without :: APrism s t a b
        -> APrism u v c d
        -> Prism (Either s u) (Either t v) (Either a c) (Either b d)
without :: forall s t a b u v c d.
APrism s t a b
-> APrism u v c d
-> Prism (Either s u) (Either t v) (Either a c) (Either b d)
without APrism s t a b
k APrism u v c d
k' =
  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         forall a b. (a -> b) -> a -> b
$ \b -> t
bt s -> Either t a
seta ->
  forall s t a b r.
APrism s t a b -> ((b -> t) -> (s -> Either t a) -> r) -> r
withPrism APrism u v c d
k'        forall a b. (a -> b) -> a -> b
$ \d -> v
dv u -> Either v c
uevc ->
  forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism (forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap b -> t
bt d -> v
dv) forall a b. (a -> b) -> a -> b
$ \Either s u
su ->
  case Either s u
su of
    Left s
s  -> forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap forall a b. a -> Either a b
Left forall a b. a -> Either a b
Left (s -> Either t a
seta s
s)
    Right u
u -> forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap forall a b. b -> Either a b
Right forall a b. b -> Either a b
Right (u -> Either v c
uevc u
u)
{-# INLINE without #-}

-- | Use a 'Prism' to work over part of a structure.

--

aside :: APrism s t a b -> Prism (e, s) (e, t) (e, a) (e, b)
aside :: forall s t a b e.
APrism s t a b -> Prism (e, s) (e, t) (e, a) (e, b)
aside APrism s t a b
k =
  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     forall a b. (a -> b) -> a -> b
$ \b -> t
bt s -> Either t a
seta ->
  forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b -> t
bt) forall a b. (a -> b) -> a -> b
$ \(e
e,s
s) ->
  case s -> Either t a
seta s
s of
    Left t
t  -> forall a b. a -> Either a b
Left  (e
e,t
t)
    Right a
a -> forall a b. b -> Either a b
Right (e
e,a
a)
{-# INLINE aside #-}

-- | 'lift' a 'Prism' through a 'Traversable' functor, giving a Prism that matches only if all the elements of the container match the 'Prism'.

--

-- >>> [Left 1, Right "foo", Left 4, Right "woot"]^..below _Right

-- []

--

-- >>> [Right "hail hydra!", Right "foo", Right "blah", Right "woot"]^..below _Right

-- [["hail hydra!","foo","blah","woot"]]

below :: Traversable f => APrism' s a -> Prism' (f s) (f a)
below :: forall (f :: * -> *) s a.
Traversable f =>
APrism' s a -> Prism' (f s) (f a)
below APrism' s a
k =
  forall s t a b r.
APrism s t a b -> ((b -> t) -> (s -> Either t a) -> r) -> r
withPrism APrism' s a
k     forall a b. (a -> b) -> a -> b
$ \a -> s
bt s -> Either s a
seta ->
  forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> s
bt) forall a b. (a -> b) -> a -> b
$ \f s
s ->
  case forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse s -> Either s a
seta f s
s of
    Left s
_  -> forall a b. a -> Either a b
Left f s
s
    Right f a
t -> forall a b. b -> Either a b
Right f a
t
{-# INLINE below #-}

-- | Check to see if this 'Prism' doesn't match.

--

-- >>> isn't _Left (Right 12)

-- True

--

-- >>> isn't _Left (Left 12)

-- False

--

-- >>> isn't _Empty []

-- False

--

-- @

-- 'isn't' = 'not' . 'Control.Lens.Extra.is'

-- 'isn't' = 'hasn't'

-- @

isn't :: APrism s t a b -> s -> Bool
isn't :: forall s t a b. APrism s t a b -> s -> Bool
isn't APrism s t a b
k s
s =
  case forall s t a b. APrism s t a b -> s -> Either t a
matching APrism s t a b
k s
s of
    Left  t
_ -> Bool
True
    Right a
_ -> Bool
False
{-# INLINE isn't #-}

-- | Retrieve the value targeted by a 'Prism' or return the

-- original value while allowing the type to change if it does

-- not match.

--

-- >>> matching _Just (Just 12)

-- Right 12

--

-- >>> matching _Just (Nothing :: Maybe Int) :: Either (Maybe Bool) Int

-- Left Nothing

matching :: APrism s t a b -> s -> Either t a
matching :: forall s t a b. APrism s t a b -> s -> Either t a
matching APrism s t a b
k = 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 forall a b. (a -> b) -> a -> b
$ \b -> t
_ s -> Either t a
seta -> s -> Either t a
seta
{-# INLINE matching #-}

-- | Like 'matching', but also works for combinations of 'Lens' and 'Prism's,

-- and also 'Traversal's.

--

-- >>> matching' (_2 . _Just) ('x', Just True)

-- Right True

--

-- >>> matching' (_2 . _Just) ('x', Nothing :: Maybe Int) :: Either (Char, Maybe Bool) Int

-- Left ('x',Nothing)

--

-- >>> matching' traverse "" :: Either [Int] Char

-- Left []

--

-- >>> matching' traverse "xyz" :: Either [Int] Char

-- Right 'x'

matching' :: LensLike (Either a) s t a b -> s -> Either t a
matching' :: forall a s t b. LensLike (Either a) s t a b -> s -> Either t a
matching' LensLike (Either a) s t a b
k = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall a b. b -> Either a b
Right forall a b. a -> Either a b
Left forall b c a. (b -> c) -> (a -> b) -> a -> c
. LensLike (Either a) s t a b
k forall a b. a -> Either a b
Left
{-# INLINE matching' #-}

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

-- Common Prisms

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


-- | This 'Prism' provides a 'Traversal' for tweaking the 'Left' half of an 'Either':

--

-- >>> over _Left (+1) (Left 2)

-- Left 3

--

-- >>> over _Left (+1) (Right 2)

-- Right 2

--

-- >>> Right 42 ^._Left :: String

-- ""

--

-- >>> Left "hello" ^._Left

-- "hello"

--

-- It also can be turned around to obtain the embedding into the 'Left' half of an 'Either':

--

-- >>> _Left # 5

-- Left 5

--

-- >>> 5^.re _Left

-- Left 5

_Left :: Prism (Either a c) (Either b c) a b
_Left :: forall a c b. Prism (Either a c) (Either b c) a b
_Left = forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall a b. b -> Either a b
Right (forall a b. a -> Either a b
Left forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. b -> Either a b
Right)
{-# INLINE _Left #-}

-- | This 'Prism' provides a 'Traversal' for tweaking the 'Right' half of an 'Either':

--

-- >>> over _Right (+1) (Left 2)

-- Left 2

--

-- >>> over _Right (+1) (Right 2)

-- Right 3

--

-- >>> Right "hello" ^._Right

-- "hello"

--

-- >>> Left "hello" ^._Right :: [Double]

-- []

--

-- It also can be turned around to obtain the embedding into the 'Right' half of an 'Either':

--

-- >>> _Right # 5

-- Right 5

--

-- >>> 5^.re _Right

-- Right 5

_Right :: Prism (Either c a) (Either c b) a b
_Right :: forall c a b. Prism (Either c a) (Either c b) a b
_Right = forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall a b. a -> Either a b
Left forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> Either a b
Left) forall a b. b -> Either a b
Right
{-# INLINE _Right #-}

-- | This 'Prism' provides a 'Traversal' for tweaking the target of the value of 'Just' in a 'Maybe'.

--

-- >>> over _Just (+1) (Just 2)

-- Just 3

--

-- Unlike 'Data.Traversable.traverse' this is a 'Prism', and so you can use it to inject as well:

--

-- >>> _Just # 5

-- Just 5

--

-- >>> 5^.re _Just

-- Just 5

--

-- Interestingly,

--

-- @

-- m '^?' '_Just' ≡ m

-- @

--

-- >>> Just x ^? _Just

-- Just x

--

-- >>> Nothing ^? _Just

-- Nothing

_Just :: Prism (Maybe a) (Maybe b) a b
_Just :: forall a b. Prism (Maybe a) (Maybe b) a b
_Just = forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall a b. a -> Either a b
Left forall a. Maybe a
Nothing) forall a b. b -> Either a b
Right
{-# INLINE _Just #-}

-- | This 'Prism' provides the 'Traversal' of a 'Nothing' in a 'Maybe'.

--

-- >>> Nothing ^? _Nothing

-- Just ()

--

-- >>> Just () ^? _Nothing

-- Nothing

--

-- But you can turn it around and use it to construct 'Nothing' as well:

--

-- >>> _Nothing # ()

-- Nothing

_Nothing :: Prism' (Maybe a) ()
_Nothing :: forall a. Prism' (Maybe a) ()
_Nothing = forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' (forall a b. a -> b -> a
const forall a. Maybe a
Nothing) forall a b. (a -> b) -> a -> b
$ forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall a. a -> Maybe a
Just ()) (forall a b. a -> b -> a
const forall a. Maybe a
Nothing)
{-# INLINE _Nothing #-}

-- | 'Void' is a logically uninhabited data type.

--

-- This is a 'Prism' that will always fail to match.

_Void :: Prism s s a Void
_Void :: forall s a. Prism s s a Void
_Void = forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism forall a. Void -> a
absurd forall a b. a -> Either a b
Left
{-# INLINE _Void #-}

-- | This 'Prism' compares for exact equality with a given value.

--

-- >>> only 4 # ()

-- 4

--

-- >>> 5 ^? only 4

-- Nothing

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


-- | This 'Prism' compares for approximate equality with a given value and a predicate for testing,

-- an example where the value is the empty list and the predicate checks that a list is empty (same

-- as 'Control.Lens.Empty._Empty' with the 'Control.Lens.Empty.AsEmpty' list instance):

--

-- >>> nearly [] null # ()

-- []

-- >>> [1,2,3,4] ^? nearly [] null

-- Nothing

--

-- @'nearly' [] 'Prelude.null' :: 'Prism'' [a] ()@

--

-- To comply with the 'Prism' laws the arguments you supply to @nearly a p@ are somewhat constrained.

--

-- We assume @p x@ holds iff @x ≡ a@. Under that assumption then this is a valid 'Prism'.

--

-- This is useful when working with a type where you can test equality for only a subset of its

-- values, and the prism selects such a value.


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

-- | This is an improper prism for text formatting based on 'Read' and 'Show'.

--

-- This 'Prism' is \"improper\" in the sense that it normalizes the text formatting, but round tripping

-- is idempotent given sane 'Read'/'Show' instances.

--

-- >>> _Show # 2

-- "2"

--

-- >>> "EQ" ^? _Show :: Maybe Ordering

-- Just EQ

--

-- @

-- '_Show' ≡ 'prism'' 'show' 'readMaybe'

-- @

_Show :: (Read a, Show a) => Prism' String a
_Show :: forall a. (Read a, Show a) => Prism' String a
_Show = forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism forall a. Show a => a -> String
show forall a b. (a -> b) -> a -> b
$ \String
s -> case forall a. Read a => ReadS a
reads String
s of
  [(a
a,String
"")] -> forall a b. b -> Either a b
Right a
a
  [(a, String)]
_ -> forall a b. a -> Either a b
Left String
s
{-# INLINE _Show #-}

class Prefixed t where
  -- | A 'Prism' stripping a prefix from a sequence when used as a 'Traversal',

  -- or prepending that prefix when run backwards:

  --

  -- >>> "preview" ^? prefixed "pre"

  -- Just "view"

  --

  -- >>> "review" ^? prefixed "pre"

  -- Nothing

  --

  -- >>> prefixed "pre" # "amble"

  -- "preamble"

  prefixed :: t -> Prism' t t

instance Eq a => Prefixed [a] where
  prefixed :: [a] -> Prism' [a] [a]
prefixed [a]
ps = forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' ([a]
ps forall a. [a] -> [a] -> [a]
++) (forall a. Eq a => [a] -> [a] -> Maybe [a]
List.stripPrefix [a]
ps)
  {-# INLINE prefixed #-}

instance Prefixed TS.Text where
  prefixed :: Text -> Prism' Text Text
prefixed Text
p = forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' (Text
p forall a. Semigroup a => a -> a -> a
<>) (Text -> Text -> Maybe Text
TS.stripPrefix Text
p)
  {-# INLINE prefixed #-}

instance Prefixed TL.Text where
  prefixed :: Text -> Prism' Text Text
prefixed Text
p = forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' (Text
p forall a. Semigroup a => a -> a -> a
<>) (Text -> Text -> Maybe Text
TL.stripPrefix Text
p)
  {-# INLINE prefixed #-}

instance Prefixed BS.ByteString where
  prefixed :: ByteString -> Prism' ByteString ByteString
prefixed ByteString
p = forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' (ByteString
p forall a. Semigroup a => a -> a -> a
<>) (ByteString -> ByteString -> Maybe ByteString
BS.stripPrefix ByteString
p)
  {-# INLINE prefixed #-}

instance Prefixed BL.ByteString where
  prefixed :: ByteString -> Prism' ByteString ByteString
prefixed ByteString
p = forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' (ByteString
p forall a. Semigroup a => a -> a -> a
<>) (ByteString -> ByteString -> Maybe ByteString
BL.stripPrefix ByteString
p)
  {-# INLINE prefixed #-}

class Suffixed t where
  -- | A 'Prism' stripping a suffix from a sequence when used as a 'Traversal',

  -- or appending that suffix when run backwards:

  --

  -- >>> "review" ^? suffixed "view"

  -- Just "re"

  --

  -- >>> "review" ^? suffixed "tire"

  -- Nothing

  --

  -- >>> suffixed ".o" # "hello"

  -- "hello.o"

  suffixed :: t -> Prism' t t

instance Eq a => Suffixed [a] where
  suffixed :: [a] -> Prism' [a] [a]
suffixed [a]
qs = forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' (forall a. [a] -> [a] -> [a]
++ [a]
qs) (forall a. Eq a => [a] -> [a] -> Maybe [a]
List.stripSuffix [a]
qs)
  {-# INLINE suffixed #-}

instance Suffixed TS.Text where
  suffixed :: Text -> Prism' Text Text
suffixed Text
qs = forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' (forall a. Semigroup a => a -> a -> a
<> Text
qs) (Text -> Text -> Maybe Text
TS.stripSuffix Text
qs)
  {-# INLINE suffixed #-}

instance Suffixed TL.Text where
  suffixed :: Text -> Prism' Text Text
suffixed Text
qs = forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' (forall a. Semigroup a => a -> a -> a
<> Text
qs) (Text -> Text -> Maybe Text
TL.stripSuffix Text
qs)
  {-# INLINE suffixed #-}

instance Suffixed BS.ByteString where
  suffixed :: ByteString -> Prism' ByteString ByteString
suffixed ByteString
qs = forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' (forall a. Semigroup a => a -> a -> a
<> ByteString
qs) (ByteString -> ByteString -> Maybe ByteString
BS.stripSuffix ByteString
qs)
  {-# INLINE suffixed #-}

instance Suffixed BL.ByteString where
  suffixed :: ByteString -> Prism' ByteString ByteString
suffixed ByteString
qs = forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' (forall a. Semigroup a => a -> a -> a
<> ByteString
qs) (ByteString -> ByteString -> Maybe ByteString
BL.stripSuffix ByteString
qs)
  {-# INLINE suffixed #-}