packages feed

gongju-0.1.0.0: src/Gongju/Adjunction.hs

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UndecidableSuperClasses #-}

-- | Module: Gongju.Adjunction
-- Description: Adjunction transitions and dual-functor annihilation for Gongju
--
-- Plugs functor adjunctions ('Adjunction', @l ⊣ r@) from 'Data.Functor.Adjunction'
-- into Gongju's open tape composition engine without modifying Core.
--
-- Provides:
-- * Adjunction unit (@η : Id ⇒ R ∘ L@) and counit (@ε : L ∘ R ⇒ Id@) stack rewrites.
-- * Day-adjoint pairing ('zapLR', 'zapRL') that annihilates dual adjoint functor
--   contexts (1 + 1 → 0 active layers).
-- * Hom-set adjunct lifting ('leftAdjunct', 'rightAdjunct').
module Gongju.Adjunction
  ( -- * Re-exported Canonical Adjunction Class
    Adjunction(..)
  , zapWithAdjunction
  , indexAdjunction
  , tabulateAdjunction
    -- * Dual Annihilation Workers
  , zapLR
  , zapRL
    -- * Open Adjunction Tags
  , PAdjU
  , PAdjC
  , PZapLR
  , PZapRL
  , PAdjL
    -- * Ergonomic Aliases
  , AdjU
  , AdjC
  , ZapLR
  , ZapRL
  , AdjL
  ) where

import Data.Functor.Adjunction
  ( Adjunction (..)
  , indexAdjunction
  , tabulateAdjunction
  , zapWithAdjunction
  )
import Gongju.Composition
  ( F
  , InOrder
  , MapPath (..)
  , StepPathMask (..)
  , StepRole (..)
  )
import Gongju.Peano (Append, Init)

-- ---------------------------------------------------------------------------
-- 1. Dual Adjoint Pairing Workers
-- ---------------------------------------------------------------------------

-- | Annihilate left adjoint context @l (a -> b)@ and right adjoint context @r a@ into @b@.
zapLR :: Adjunction l r => l (a -> b) -> r a -> b
zapLR lab ra = counit (fmap (<$> ra) lab)
{-# INLINE zapLR #-}

-- | Dual annihilation: @r (a -> b)@ and @l a@ into @b@.
zapRL :: Adjunction l r => r (a -> b) -> l a -> b
zapRL rab la = counit (fmap (\a -> fmap ($ a) rab) la)
{-# INLINE zapRL #-}

-- ---------------------------------------------------------------------------
-- 2. Open Mode Tags & Aliases
-- ---------------------------------------------------------------------------

-- | Tag for inserting an adjunction unit: @a -> r (l a)@.
data PAdjU

-- | Tag for applying an adjunction counit: @l (r a) -> a@.
data PAdjC

-- | Tag for pairing active left-adjoint @l (a -> b)@ against caller @r a@ (annihilating both).
data PZapLR

-- | Tag for pairing active right-adjoint @r (a -> b)@ against caller @l a@ (annihilating both).
data PZapRL

-- | Tag for applying 'leftAdjunct': turns expectation of @l a@ into caller passing pure @a@.
data PAdjL

-- | In-order adjunction unit alias.
type AdjU = InOrder PAdjU

-- | In-order adjunction counit alias.
type AdjC = InOrder PAdjC

-- | In-order Day-adjoint pairing alias (left active, right caller).
type ZapLR = InOrder PZapLR

-- | In-order Day-adjoint pairing alias (right active, left caller).
type ZapRL = InOrder PZapRL

-- | In-order hom-set adjunct alias.
type AdjL = InOrder PAdjL

-- ---------------------------------------------------------------------------
-- 3. StepRole Instances (Adjunction Transitions)
-- ---------------------------------------------------------------------------

-- | Adjunction unit: expands inner tip to @r (l inner)@.
instance forall base active ms m t3 acc acc' out l r inner.
  ( Adjunction l r
  , MapPath (Init active) inner (r (l inner)) acc acc'
  , StepPathMask base (Append active '[ F, F ]) ms m t3 acc' out
  ) => StepRole PAdjU base active ms m t3 acc out where
  stepRole f acc =
    stepPathMask @base @(Append active '[ F, F ]) @ms @m @t3 @acc' @out f
      (mapPath @(Init active) @inner @(r (l inner)) unit acc)
  {-# INLINE stepRole #-}

-- | Adjunction counit: collapses @l (r inner)@ at the tip down to @inner@.
instance forall base active ms m t3 acc acc' out l r inner.
  ( Adjunction l r
  , MapPath (Init (Init active)) (l (r inner)) inner acc acc'
  , StepPathMask base (Init (Init active)) ms m t3 acc' out
  ) => StepRole PAdjC base active ms m t3 acc out where
  stepRole f acc =
    stepPathMask @base @(Init (Init active)) @ms @m @t3 @acc' @out f
      (mapPath @(Init (Init active)) @(l (r inner)) @inner counit acc)
  {-# INLINE stepRole #-}

-- | ZapLR: Annihilates active left-adjoint layer with caller right-adjoint argument.
instance forall base active ms m t3 acc acc' out' l r a rem ra.
  ( Adjunction l r
  , ra ~ r a
  , MapPath (Init active) (l (a -> rem)) rem acc acc'
  , StepPathMask base (Init active) ms m t3 acc' out'
  ) => StepRole PZapLR base active ms m t3 acc (ra -> out') where
  stepRole f acc ra =
    stepPathMask @base @(Init active) @ms @m @t3 @acc' @out' f
      (mapPath @(Init active) @(l (a -> rem)) @rem (`zapLR` ra) acc)
  {-# INLINE stepRole #-}

-- | ZapRL: Annihilates active right-adjoint layer with caller left-adjoint argument.
instance forall base active ms m t3 acc acc' out' l r a rem la.
  ( Adjunction l r
  , la ~ l a
  , MapPath (Init active) (r (a -> rem)) rem acc acc'
  , StepPathMask base (Init active) ms m t3 acc' out'
  ) => StepRole PZapRL base active ms m t3 acc (la -> out') where
  stepRole f acc la =
    stepPathMask @base @(Init active) @ms @m @t3 @acc' @out' f
      (mapPath @(Init active) @(r (a -> rem)) @rem (`zapRL` la) acc)
  {-# INLINE stepRole #-}

-- | AdjL: Turns @l a -> rem@ in the accumulator into @a -> r rem@.
instance forall base active ms m t3 acc acc' out' l r a rem.
  ( Adjunction l r
  , MapPath active (l a -> rem) (r rem) acc acc'
  , StepPathMask base (Append active '[ F ]) ms m t3 acc' out'
  ) => StepRole PAdjL base active ms m t3 acc (a -> out') where
  stepRole f acc a =
    stepPathMask @base @(Append active '[ F ]) @ms @m @t3 @acc' @out' f
      (mapPath @active @(l a -> rem) @(r rem) (`leftAdjunct` a) acc)
  {-# INLINE stepRole #-}