{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Barbies.Internal.FunctorT
( FunctorT(..)
, gtmapDefault
, CanDeriveFunctorT
)
where
import Barbies.Generics.Functor (GFunctor(..))
import Control.Applicative.Backwards(Backwards (..))
import Control.Applicative.Lift(Lift, mapLift )
import Control.Monad.Trans.Except(ExceptT, mapExceptT)
import Control.Monad.Trans.Identity(IdentityT, mapIdentityT)
import Control.Monad.Trans.Maybe(MaybeT, mapMaybeT)
import Control.Monad.Trans.RWS.Lazy as Lazy (RWST, mapRWST)
import Control.Monad.Trans.RWS.Strict as Strict (RWST, mapRWST)
import Control.Monad.Trans.Reader(ReaderT, mapReaderT)
import Control.Monad.Trans.State.Lazy as Lazy (StateT, mapStateT)
import Control.Monad.Trans.State.Strict as Strict (StateT, mapStateT)
import Control.Monad.Trans.Writer.Lazy as Lazy (WriterT, mapWriterT)
import Control.Monad.Trans.Writer.Strict as Strict (WriterT, mapWriterT)
import Data.Functor.Compose (Compose (..))
import Data.Functor.Product (Product (..))
import Data.Functor.Reverse (Reverse (..))
import Data.Functor.Sum (Sum (..))
import Data.Generics.GenericN
import Data.Proxy (Proxy (..))
import Data.Kind (Type)
class FunctorT (t :: (k -> Type) -> k' -> Type) where
tmap :: (forall a . f a -> g a) -> (forall x. t f x -> t g x)
default tmap
:: forall f g x
. CanDeriveFunctorT t f g x
=> (forall a . f a -> g a)
-> t f x
-> t g x
tmap = gtmapDefault
type CanDeriveFunctorT t f g x
= ( GenericP 1 (t f x)
, GenericP 1 (t g x)
, GFunctor 1 f g (RepP 1 (t f x)) (RepP 1 (t g x))
)
gtmapDefault
:: CanDeriveFunctorT t f g x
=> (forall a . f a -> g a)
-> t f x
-> t g x
gtmapDefault f
= toP (Proxy @1) . gmap (Proxy @1) f . fromP (Proxy @1)
{-# INLINE gtmapDefault #-}
type P = Param
instance
( FunctorT t
) => GFunctor 1 f g (Rec (t (P 1 f) x) (t f x))
(Rec (t (P 1 g) x) (t g x))
where
gmap _ h (Rec (K1 tf)) = Rec (K1 (tmap h tf))
{-# INLINE gmap #-}
instance
( Functor h
, FunctorT t
) => GFunctor 1 f g (Rec (h (t (P 1 f) x)) (h (t f x)))
(Rec (h (t (P 1 g) x)) (h (t g x)))
where
gmap _ h (Rec (K1 htf)) = Rec (K1 (fmap (tmap h) htf))
{-# INLINE gmap #-}
instance
( Functor h
, Functor m
, FunctorT t
) => GFunctor 1 f g (Rec (m (h (t (P 1 f) x))) (m (h (t f x))))
(Rec (m (h (t (P 1 g) x))) (m (h (t g x))))
where
gmap _ h (Rec (K1 mhtf)) = Rec (K1 (fmap (fmap (tmap h)) mhtf))
{-# INLINE gmap #-}
instance Functor f => FunctorT (Compose f) where
tmap h (Compose fga)
= Compose (fmap h fga)
{-# INLINE tmap #-}
instance FunctorT (Product f) where
tmap h (Pair fa ga) = Pair fa (h ga)
{-# INLINE tmap #-}
instance FunctorT (Sum f) where
tmap h = \case
InL fa -> InL fa
InR ga -> InR (h ga)
{-# INLINE tmap #-}
instance FunctorT Backwards where
tmap h (Backwards fa)
= Backwards (h fa)
{-# INLINE tmap #-}
instance FunctorT Reverse where
tmap h (Reverse fa) = Reverse (h fa)
{-# INLINE tmap #-}
instance FunctorT Lift where
tmap h = mapLift h
{-# INLINE tmap #-}
instance FunctorT (ExceptT e) where
tmap h = mapExceptT h
{-# INLINE tmap #-}
instance FunctorT IdentityT where
tmap h = mapIdentityT h
{-# INLINE tmap #-}
instance FunctorT MaybeT where
tmap h = mapMaybeT h
{-# INLINE tmap #-}
instance FunctorT (Lazy.RWST r w s) where
tmap h = Lazy.mapRWST h
{-# INLINE tmap #-}
instance FunctorT (Strict.RWST r w s) where
tmap h = Strict.mapRWST h
{-# INLINE tmap #-}
instance FunctorT (ReaderT r) where
tmap h = mapReaderT h
{-# INLINE tmap #-}
instance FunctorT (Lazy.StateT s) where
tmap h = Lazy.mapStateT h
{-# INLINE tmap #-}
instance FunctorT (Strict.StateT s) where
tmap h = Strict.mapStateT h
{-# INLINE tmap #-}
instance FunctorT (Lazy.WriterT w) where
tmap h = Lazy.mapWriterT h
{-# INLINE tmap #-}
instance FunctorT (Strict.WriterT w) where
tmap h = Strict.mapWriterT h
{-# INLINE tmap #-}