{-# OPTIONS_HADDOCK hide #-}
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE GADTs                     #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE Rank2Types                #-}
{-# LANGUAGE ScopedTypeVariables       #-}
{-# LANGUAGE TypeFamilies              #-}
{-# LANGUAGE TypeFamilyDependencies    #-}
{-# LANGUAGE TypeOperators             #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Data.Generics.Internal.VL.Prism
-- Copyright   :  (C) 2020 Csongor Kiss
-- License     :  BSD3
-- Maintainer  :  Csongor Kiss <kiss.csongor.kiss@gmail.com>
-- Stability   :  experimental
-- Portability :  non-portable
--
-- Internal lens helpers. Only exported for Haddock
--
-----------------------------------------------------------------------------
module Data.Generics.Internal.VL.Prism where

import qualified "generic-lens-core" Data.Generics.Internal.Profunctor.Prism as P

import qualified Data.Profunctor as P
import Data.Functor.Identity (Identity (..))
import Data.Coerce (coerce)

-- | Type alias for prism
type Prism s t a b
  = forall p f. (P.Choice p, Applicative f) => p a (f b) -> p s (f t)

type Prism' s a
  = Prism s s a a

match :: Prism s t a b -> s -> Either t a
match :: Prism s t a b -> s -> Either t a
match Prism s t a b
p = case Market a b a (Identity b) -> Market a b s (Identity t)
Prism s t a b
p ((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 -> Identity t
_ s -> Either (Identity t) a
seta -> (s -> Either (Identity t) a) -> s -> Either t a
coerce s -> Either (Identity t) a
seta
{-# INLINE match #-}

build :: Prism s t a b -> b -> t
build :: Prism s t a b -> b -> t
build Prism s t a b
p = case Market a b a (Identity b) -> Market a b s (Identity t)
Prism s t a b
p ((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 -> Identity t
bt s -> Either (Identity t) a
_ -> (b -> Identity t) -> b -> t
coerce b -> Identity t
bt
{-# INLINE build #-}

prism :: (b -> t) -> (s -> Either t a) -> Prism s t a b
prism :: (b -> t) -> (s -> Either t a) -> Prism s t a b
prism b -> t
bt s -> Either t a
seta p a (f b)
eta = (s -> Either (f t) a)
-> (Either (f t) (f b) -> f t)
-> p (Either (f t) a) (Either (f t) (f b))
-> p s (f t)
forall (p :: * -> * -> *) a b c d.
Profunctor p =>
(a -> b) -> (c -> d) -> p b c -> p a d
P.dimap (\s
x -> (t -> f t) -> Either t a -> Either (f t) a
forall (p :: * -> * -> *) a b c.
Choice p =>
p a b -> p (Either a c) (Either b c)
P.left' t -> f t
forall (f :: * -> *) a. Applicative f => a -> f a
pure (s -> Either t a
seta s
x)) ((f t -> f t) -> (f b -> f t) -> Either (f t) (f b) -> f t
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either f t -> f t
forall a. a -> a
id (\f b
x -> (b -> t) -> f b -> f t
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b -> t
bt f b
x)) (p a (f b) -> p (Either (f t) a) (Either (f t) (f b))
forall (p :: * -> * -> *) a b c.
Choice p =>
p a b -> p (Either c a) (Either c b)
P.right' p a (f b)
eta)
{-# INLINE prism #-}

prism2prismvl :: P.APrism i s t a b -> Prism s t a b
prism2prismvl :: APrism i s t a b -> Prism s t a b
prism2prismvl  APrism i s t a b
_prism = APrism i 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 i s t a b r.
APrism i s t a b -> ((b -> t) -> (s -> Either t a) -> r) -> r
P.withPrism APrism i s t a b
_prism (((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 prism2prismvl #-}

--------------------------------------------------------------------------------
-- Market

data Market a b s t = Market (b -> t) (s -> Either t a)

instance Functor (Market a b s) where
  fmap :: (a -> b) -> Market a b s a -> Market a b s b
fmap a -> b
f (Market b -> a
bt s -> Either a a
seta) = (b -> b) -> (s -> Either b a) -> Market a b s b
forall a b s t. (b -> t) -> (s -> Either t a) -> Market a b s t
Market (a -> b
f (a -> b) -> (b -> a) -> b -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> a
bt) ((a -> Either b a) -> (a -> Either b a) -> Either a a -> Either b a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (b -> Either b a
forall a b. a -> Either a b
Left (b -> Either b a) -> (a -> b) -> a -> Either b a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f) a -> Either b a
forall a b. b -> Either a b
Right (Either a a -> Either b a) -> (s -> Either a a) -> s -> Either b a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> Either a a
seta)
  {-# INLINE fmap #-}

instance P.Profunctor (Market a b) where
  dimap :: (a -> b) -> (c -> d) -> Market a b b c -> Market a b a d
dimap a -> b
f c -> d
g (Market b -> c
bt b -> Either c a
seta) = (b -> d) -> (a -> Either d a) -> Market a b a d
forall a b s t. (b -> t) -> (s -> Either t a) -> Market a b s t
Market (c -> d
g (c -> d) -> (b -> c) -> b -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> c
bt) ((c -> Either d a) -> (a -> Either d a) -> Either c a -> Either d a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (d -> Either d a
forall a b. a -> Either a b
Left (d -> Either d a) -> (c -> d) -> c -> Either d a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. c -> d
g) a -> Either d a
forall a b. b -> Either a b
Right (Either c a -> Either d a) -> (a -> Either c a) -> a -> Either d a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> Either c a
seta (b -> Either c a) -> (a -> b) -> a -> Either c a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f)
  {-# INLINE dimap #-}
  lmap :: (a -> b) -> Market a b b c -> Market a b a c
lmap a -> b
f (Market b -> c
bt b -> Either c a
seta) = (b -> c) -> (a -> Either c a) -> Market a b a c
forall a b s t. (b -> t) -> (s -> Either t a) -> Market a b s t
Market b -> c
bt (b -> Either c a
seta (b -> Either c a) -> (a -> b) -> a -> Either c a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f)
  {-# INLINE lmap #-}
  rmap :: (b -> c) -> Market a b a b -> Market a b a c
rmap b -> c
f (Market b -> b
bt a -> Either b a
seta) = (b -> c) -> (a -> Either c a) -> Market a b a c
forall a b s t. (b -> t) -> (s -> Either t a) -> Market a b s t
Market (b -> c
f (b -> c) -> (b -> b) -> b -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> b
bt) ((b -> Either c a) -> (a -> Either c a) -> Either b a -> Either c a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (c -> Either c a
forall a b. a -> Either a b
Left (c -> Either c a) -> (b -> c) -> b -> Either c a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> c
f) a -> Either c a
forall a b. b -> Either a b
Right (Either b a -> Either c a) -> (a -> Either b a) -> a -> Either c a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Either b a
seta)
  {-# INLINE rmap #-}

instance P.Choice (Market a b) where
  left' :: Market a b a b -> Market a b (Either a c) (Either b c)
left' (Market b -> b
bt a -> Either b a
seta) = (b -> Either b c)
-> (Either a c -> Either (Either b c) a)
-> Market a b (Either a c) (Either b c)
forall a b s t. (b -> t) -> (s -> Either t a) -> Market a b s t
Market (b -> Either b c
forall a b. a -> Either a b
Left (b -> Either b c) -> (b -> b) -> b -> Either b c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> b
bt) ((Either a c -> Either (Either b c) a)
 -> Market a b (Either a c) (Either b c))
-> (Either a c -> Either (Either b c) a)
-> Market a b (Either a c) (Either b c)
forall a b. (a -> b) -> a -> b
$ \Either a c
sc -> case Either a c
sc of
    Left a
s -> case a -> Either b a
seta a
s of
      Left b
t -> Either b c -> Either (Either b c) a
forall a b. a -> Either a b
Left (b -> Either b c
forall a b. a -> Either a b
Left b
t)
      Right a
a -> a -> Either (Either b c) a
forall a b. b -> Either a b
Right a
a
    Right c
c -> Either b c -> Either (Either b c) a
forall a b. a -> Either a b
Left (c -> Either b c
forall a b. b -> Either a b
Right c
c)
  {-# INLINE left' #-}
  right' :: Market a b a b -> Market a b (Either c a) (Either c b)
right' (Market b -> b
bt a -> Either b a
seta) = (b -> Either c b)
-> (Either c a -> Either (Either c b) a)
-> Market a b (Either c a) (Either c b)
forall a b s t. (b -> t) -> (s -> Either t a) -> Market a b s t
Market (b -> Either c b
forall a b. b -> Either a b
Right (b -> Either c b) -> (b -> b) -> b -> Either c b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> b
bt) ((Either c a -> Either (Either c b) a)
 -> Market a b (Either c a) (Either c b))
-> (Either c a -> Either (Either c b) a)
-> Market a b (Either c a) (Either c b)
forall a b. (a -> b) -> a -> b
$ \Either c a
cs -> case Either c a
cs of
    Left c
c -> Either c b -> Either (Either c b) a
forall a b. a -> Either a b
Left (c -> Either c b
forall a b. a -> Either a b
Left c
c)
    Right a
s -> case a -> Either b a
seta a
s of
      Left b
t -> Either c b -> Either (Either c b) a
forall a b. a -> Either a b
Left (b -> Either c b
forall a b. b -> Either a b
Right b
t)
      Right a
a -> a -> Either (Either c b) a
forall a b. b -> Either a b
Right a
a
  {-# INLINE right' #-}