gongju-0.1.0.0: src/Gongju/Indexed.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.Indexed
-- Description: Indexed Monads and Indexed Comonads for Gongju
--
-- Plugs indexed functorial structures ('IxFunctor', 'IxApplicative', 'IxMonad',
-- 'IxComonad') into Gongju's open tape composition engine without modifying Core.
module Gongju.Indexed
( -- * Re-exported Canonical Indexed Classes
IxFunctor(..)
, IxPointed(..)
, IxCopointed(..)
, IxApplicative(..)
, ipure
, iliftA2
, IxMonad(..)
, (>>>=)
, (=<<<)
, ijoin
, IxComonad(..)
, iduplicate
-- * Open Indexed Tags
, IxF
, PIM
, IJ
, PIxW
, IxDup
, IxEx
-- * Ergonomic Aliases
, IxM
, IxW
) where
import Control.Comonad.Indexed
( IxComonad (..)
, iduplicate
)
import Control.Monad.Indexed
( IxApplicative (..)
, IxMonad (..)
, ijoin
, (=<<<)
, (>>>=)
)
import Data.Functor.Indexed
( IxCopointed (..)
, IxFunctor (..)
, IxPointed (..)
)
import Data.Kind (Type)
import Gongju.Composition
( ApPath (..)
, ApStep (..)
, InOrder
, MapPath (..)
, MapStep (..)
, StepPathMask (..)
, StepRole (..)
)
import Gongju.Peano (Append, Init)
import Gongju.Positional (ExpectArrow)
-- | Ergonomic alias for 'ireturn'.
ipure :: IxPointed m => a -> m i i a
ipure = ireturn
{-# INLINE ipure #-}
-- | Lift a binary function across two indexed applicatives.
iliftA2 :: IxApplicative m => (a -> b -> c) -> m i j a -> m j l b -> m i l c
iliftA2 f ma mb = iap (imap f ma) mb
{-# INLINE iliftA2 #-}
-- ---------------------------------------------------------------------------
-- 2. Open Indexed Tags
-- ---------------------------------------------------------------------------
-- | Tag for an indexed functor layer @m i j a@.
data IxF
-- | Tag for indexed monadic bind ('ibind').
data PIM
-- | Tag for indexed monadic join ('ijoin').
data IJ
-- | Tag for indexed comonadic extend ('iextend').
data PIxW
-- | Tag for indexed comonadic duplication ('iduplicate').
data IxDup
-- | Tag for indexed comonadic extraction ('iextract').
data IxEx
-- | In-order unindexed indexed monad bind alias.
type IxM = InOrder PIM
-- | In-order unindexed indexed comonad extend alias.
type IxW = InOrder PIxW
-- ---------------------------------------------------------------------------
-- 3. Mapping & Zipping Instances
-- ---------------------------------------------------------------------------
instance (IxFunctor m, s ~ m i j s', t ~ m i j t', MapPath ls a b s' t')
=> MapStep IxF ls a b s t where
mapStep f = imap (mapPath @ls f)
{-# INLINE mapStep #-}
instance (IxApplicative m, fab ~ m i j fab', fa ~ m j l fa', fb ~ m i l fb', ApPath ls fab' fa' fb')
=> ApStep IxF ls fab fa fb where
apStep = iliftA2 (apPath @ls)
{-# INLINE apStep #-}
-- ---------------------------------------------------------------------------
-- 4. StepRole Instances (IxMonad & IxComonad Transitions)
-- ---------------------------------------------------------------------------
instance (IxMonad φ, ExpectArrow "StepRole PIM" acc a rTail, fa ~ φ i j a, StepPathMask base '[ IxF ] ms m t3 (φ i j rTail) out')
=> StepRole PIM base '[] ms m t3 acc (fa -> out') where
stepRole f acc fa = stepPathMask @base @'[ IxF ] @ms f (imap acc fa)
{-# INLINE stepRole #-}
instance forall base l ls ms m t3 acc acc' out' idx (φ :: idx -> idx -> Type -> Type) i j rIdx a rTail fa.
( IxMonad φ, fa ~ φ j rIdx a
, MapPath (Init (l ': ls)) (φ i j (a -> rTail)) (φ i rIdx rTail) acc acc'
, StepPathMask base (l ': ls) ms m t3 acc' out'
) => StepRole PIM base (l ': ls) ms m t3 acc (fa -> out') where
stepRole f acc fa =
stepPathMask @base @(l ': ls) @ms @m @t3 @acc' @out' f
(mapPath @(Init (l ': ls)) @(φ i j (a -> rTail)) @(φ i rIdx rTail)
(\mf -> mf >>>= (`imap` fa)) acc)
{-# INLINE stepRole #-}
instance forall base active ms m t3 acc acc' out idx (φ :: idx -> idx -> Type -> Type) i j rIdx inner.
( IxMonad φ
, MapPath (Init active) (φ i j (φ j rIdx inner)) (φ i rIdx inner) acc acc'
, StepPathMask base active ms m t3 acc' out
) => StepRole IJ base active ms m t3 acc out where
stepRole f acc =
stepPathMask @base @active @ms @m @t3 @acc' @out f
(mapPath @(Init active) @(φ i j (φ j rIdx inner)) @(φ i rIdx inner) ijoin acc)
{-# INLINE stepRole #-}
instance ( IxComonad w
, ExpectArrow "StepRole PIxW" acc (w j k a) rTail
, wa ~ w i k a
, StepPathMask base '[ IxF ] ms m t3 (w i j rTail) out'
) => StepRole PIxW base '[] ms m t3 acc (wa -> out') where
stepRole f acc wa = stepPathMask @base @'[ IxF ] @ms f (iextend acc wa)
{-# INLINE stepRole #-}
instance forall base active ms m t3 acc acc' out' knd (w :: knd -> knd -> Type -> Type) i j k a rTail wa.
( IxComonad w
, wa ~ w i k a
, MapPath active (w j k a -> rTail) (w i j rTail) acc acc'
, StepPathMask base (Append active '[ IxF ]) ms m t3 acc' out'
) => StepRole PIxW base active ms m t3 acc (wa -> out') where
stepRole f acc wa =
stepPathMask @base @(Append active '[ IxF ]) @ms @m @t3 @acc' @out' f
(mapPath @active @(w j k a -> rTail) @(w i j rTail) (`iextend` wa) acc)
{-# INLINE stepRole #-}
instance forall base active ms m t3 acc acc' out knd (w :: knd -> knd -> Type -> Type) i j k inner.
( IxComonad w
, MapPath (Init active) (w i k inner) (w i j (w j k inner)) acc acc'
, StepPathMask base (Append active '[ IxF ]) ms m t3 acc' out
) => StepRole IxDup base active ms m t3 acc out where
stepRole f acc =
stepPathMask @base @(Append active '[ IxF ]) @ms @m @t3 @acc' @out f
(mapPath @(Init active) @(w i k inner) @(w i j (w j k inner)) iduplicate acc)
{-# INLINE stepRole #-}
instance forall base active ms m t3 acc acc' out knd (w :: knd -> knd -> Type -> Type) i inner.
( IxComonad w
, MapPath (Init active) (w i i inner) inner acc acc'
, StepPathMask base (Init active) ms m t3 acc' out
) => StepRole IxEx base active ms m t3 acc out where
stepRole f acc =
stepPathMask @base @(Init active) @ms @m @t3 @acc' @out f
(mapPath @(Init active) @(w i i inner) @inner iextract acc)
{-# INLINE stepRole #-}