functor-monad-0.1.1.0: src/FComonad/Adjoint.hs
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE StandaloneDeriving #-}
module FComonad.Adjoint(Adjoint, adjoint, runAdjoint, AdjointT(..), fffmap, ungeneralize) where
import Control.Monad.Trans.Identity ( IdentityT(..) )
import FFunctor
import FComonad
import FStrong
import FFunctor.FCompose
import FFunctor.Adjunction
newtype AdjointT ff uu ww g x = AdjointT { runAdjointT :: ff (ww (uu g)) x }
deriving Functor
type Adjoint ff uu = AdjointT ff uu IdentityT
deriving
via FCompose (FCompose ff ww) uu
instance (FFunctor ff, FFunctor ww, FFunctor uu) => FFunctor (AdjointT ff uu ww)
deriving
via FCompose (FCompose ff ww) uu
instance (FStrong ff, FStrong ww, FStrong uu) => FStrong (AdjointT ff uu ww)
instance (Adjunction ff uu, FComonad ww) => FComonad (AdjointT ff uu ww) where
fextract = counit . ffmap fextract . runAdjointT
fextend tr = ffmap (tr . AdjointT) . AdjointT . ffmap (fextend unit) . runAdjointT
adjoint :: (FFunctor ff, FFunctor uu, Functor x) => ff (uu x) ~> Adjoint ff uu x
adjoint = AdjointT . ffmap IdentityT
runAdjoint :: (FFunctor ff, FFunctor uu, Functor x) => Adjoint ff uu x ~> ff (uu x)
runAdjoint = ffmap runIdentityT . runAdjointT
fffmap :: forall mm nn ff uu x.
(FFunctor mm, FFunctor nn, FFunctor ff, FFunctor uu, Functor x)
=> (forall y. (Functor y) => mm y ~> nn y)
-> (AdjointT ff uu mm x ~> AdjointT ff uu nn x)
fffmap trans = AdjointT . ffmap trans . runAdjointT
ungeneralize :: (FComonad ww, FFunctor ff, FFunctor uu, Functor x) => AdjointT ff uu ww x ~> Adjoint ff uu x
ungeneralize = fffmap (IdentityT . fextract)