{-# LANGUAGE DerivingVia, StandaloneDeriving, TypeOperators #-}
module Control.Subcategory.Pointed where
import Control.Subcategory.Functor

import qualified Control.Applicative             as App
import qualified Control.Monad.ST.Lazy           as LST
import qualified Control.Monad.ST.Strict         as SST
import qualified Data.Functor.Compose            as SOP
import           Data.Functor.Identity           (Identity)
import qualified Data.Functor.Product            as SOP
import qualified Data.HashSet                    as HS
import qualified Data.IntSet                     as IS
import           Data.List.NonEmpty              (NonEmpty)
import qualified Data.Monoid                     as Mon
import           Data.MonoTraversable            (MonoPointed, opoint)
import           Data.Ord                        (Down)
import qualified Data.Pointed                    as Pt
import qualified Data.Primitive.Array            as A
import qualified Data.Primitive.PrimArray        as PA
import qualified Data.Primitive.SmallArray       as SA
import           Data.Proxy                      (Proxy)
import qualified Data.Semigroup                  as Sem
import qualified Data.Sequence                   as Seq
import qualified Data.Set                        as Set
import qualified Data.Tree                       as Tree
import qualified Data.Vector                     as V
import qualified Data.Vector.Primitive           as P
import qualified Data.Vector.Storable            as S
import qualified Data.Vector.Unboxed             as U
import           GHC.Conc                        (STM)
import           GHC.Generics                    ((:*:) (..), (:.:) (..))
import           GHC.Generics                    (Par1, Rec1, U1)
import           Text.ParserCombinators.ReadP    (ReadP)
import           Text.ParserCombinators.ReadPrec (ReadPrec)

class Constrained f => CPointed f where
  cpure :: Dom f a => a -> f a
  default cpure :: App.Applicative f => a -> f a
  cpure = a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure

instance (Functor f, Pt.Pointed f) => CPointed (WrapFunctor f) where
  cpure :: a -> WrapFunctor f a
cpure = a -> WrapFunctor f a
forall (p :: * -> *) a. Pointed p => a -> p a
Pt.point
  {-# INLINE cpure #-}

instance CPointed []
instance CPointed Maybe
instance CPointed IO
instance CPointed (SST.ST s)
instance CPointed (LST.ST s)
instance CPointed Par1
instance CPointed Sem.Min
instance CPointed Sem.Max
instance CPointed Mon.First
instance CPointed Mon.Last
instance CPointed Sem.First
instance CPointed Sem.Last
instance CPointed Sem.Option
instance CPointed NonEmpty
instance CPointed App.ZipList
instance CPointed Identity
instance CPointed STM
instance CPointed Sem.Dual
instance CPointed Sem.Sum
instance CPointed Sem.Product
instance CPointed Down
instance CPointed Tree.Tree
instance CPointed Seq.Seq
instance CPointed Set.Set where
  cpure :: a -> Set a
cpure = a -> Set a
forall a. a -> Set a
Set.singleton
  {-# INLINE cpure #-}
instance CPointed (Either a)
instance CPointed U1
instance CPointed Proxy
instance (Pt.Pointed f) => CPointed (Rec1 f) where
  cpure :: a -> Rec1 f a
cpure = a -> Rec1 f a
forall (p :: * -> *) a. Pointed p => a -> p a
Pt.point
  {-# INLINE cpure #-}
instance (Pt.Pointed p, Pt.Pointed q)
      => CPointed (p :*: q) where
  cpure :: a -> (:*:) p q a
cpure a
a = p a -> q a -> (:*:) p q a
forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
(:*:) (a -> p a
forall (p :: * -> *) a. Pointed p => a -> p a
Pt.point a
a) (a -> q a
forall (p :: * -> *) a. Pointed p => a -> p a
Pt.point a
a)
  {-# INLINE cpure #-}
instance (Pt.Pointed p, Pt.Pointed q)
      => CPointed (p :.: q) where
  cpure :: a -> (:.:) p q a
cpure a
a = p (q a) -> (:.:) p q a
forall k2 k1 (f :: k2 -> *) (g :: k1 -> k2) (p :: k1).
f (g p) -> (:.:) f g p
Comp1 (p (q a) -> (:.:) p q a) -> p (q a) -> (:.:) p q a
forall a b. (a -> b) -> a -> b
$ q a -> p (q a)
forall (p :: * -> *) a. Pointed p => a -> p a
Pt.point (q a -> p (q a)) -> q a -> p (q a)
forall a b. (a -> b) -> a -> b
$ a -> q a
forall (p :: * -> *) a. Pointed p => a -> p a
Pt.point a
a
  {-# INLINE cpure #-}
instance (Constrained p, Constrained q, Pt.Pointed p, Pt.Pointed q)
      => CPointed (SOP.Compose p q) where
  cpure :: a -> Compose p q a
cpure a
a = p (q a) -> Compose p q a
forall k k1 (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
SOP.Compose (p (q a) -> Compose p q a) -> p (q a) -> Compose p q a
forall a b. (a -> b) -> a -> b
$ q a -> p (q a)
forall (p :: * -> *) a. Pointed p => a -> p a
Pt.point (q a -> p (q a)) -> q a -> p (q a)
forall a b. (a -> b) -> a -> b
$ a -> q a
forall (p :: * -> *) a. Pointed p => a -> p a
Pt.point a
a
  {-# INLINE cpure #-}
instance (CPointed p, CPointed q)
      => CPointed (SOP.Product p q) where
  cpure :: a -> Product p q a
cpure a
a = p a -> q a -> Product p q a
forall k (f :: k -> *) (g :: k -> *) (a :: k).
f a -> g a -> Product f g a
SOP.Pair (a -> p a
forall (f :: * -> *) a. (CPointed f, Dom f a) => a -> f a
cpure a
a) (a -> q a
forall (f :: * -> *) a. (CPointed f, Dom f a) => a -> f a
cpure a
a)
  {-# INLINE cpure #-}
instance CPointed ReadP
instance CPointed ReadPrec
instance CPointed (WrapMono IS.IntSet) where
  cpure :: a -> WrapMono IntSet a
cpure = IntSet -> WrapMono IntSet a
forall b mono.
(b ~ Element mono, b ~ Element mono) =>
mono -> WrapMono mono b
WrapMono (IntSet -> WrapMono IntSet a)
-> (Key -> IntSet) -> Key -> WrapMono IntSet a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Key -> IntSet
IS.singleton
  {-# INLINE cpure #-}
instance CPointed HS.HashSet where
  cpure :: a -> HashSet a
cpure = a -> HashSet a
forall a. Hashable a => a -> HashSet a
HS.singleton
  {-# INLINE cpure #-}

instance MonoPointed mono => CPointed (WrapMono mono) where
  cpure :: a -> WrapMono mono a
cpure = a -> WrapMono mono a
forall mono. MonoPointed mono => Element mono -> mono
opoint

instance CPointed V.Vector where
  cpure :: a -> Vector a
cpure = a -> Vector a
forall a. a -> Vector a
V.singleton
  {-# INLINE [1] cpure #-}

instance CPointed U.Vector where
  cpure :: a -> Vector a
cpure = a -> Vector a
forall a. Unbox a => a -> Vector a
U.singleton
  {-# INLINE [1] cpure #-}

instance CPointed S.Vector where
  cpure :: a -> Vector a
cpure = a -> Vector a
forall a. Storable a => a -> Vector a
S.singleton
  {-# INLINE [1] cpure #-}

instance CPointed P.Vector where
  cpure :: a -> Vector a
cpure = a -> Vector a
forall a. Prim a => a -> Vector a
P.singleton
  {-# INLINE [1] cpure #-}

instance CPointed PA.PrimArray where
  cpure :: a -> PrimArray a
cpure = Key -> a -> PrimArray a
forall a. Prim a => Key -> a -> PrimArray a
PA.replicatePrimArray Key
1
  {-# INLINE [1] cpure #-}

instance CPointed SA.SmallArray where
  cpure :: a -> SmallArray a
cpure = Key -> [a] -> SmallArray a
forall a. Key -> [a] -> SmallArray a
SA.smallArrayFromListN Key
1 ([a] -> SmallArray a) -> (a -> [a]) -> a -> SmallArray a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure
  {-# INLINE [1] cpure #-}

instance CPointed A.Array where
  cpure :: a -> Array a
cpure = Key -> [Item (Array a)] -> Array a
forall l. IsList l => Key -> [Item l] -> l
A.fromListN Key
1 ([a] -> Array a) -> (a -> [a]) -> a -> Array a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure
  {-# INLINE [1] cpure #-}