module Data.Expression.Utils.Indexed.Functor (IFix(..), IFunctor(..), icata) where
import Data.Functor.Const
import Data.Kind
import Data.Singletons
import Data.Expression.Utils.Indexed.Eq
import Data.Expression.Utils.Indexed.Show
newtype IFix f i = IFix { unIFix :: f (IFix f) i }
class IFunctor (f :: (i -> *) -> (i -> *)) where
imap :: (forall i'. a i' -> b i') -> (forall i'. f a i' -> f b i')
index :: forall a i'. f a i' -> Sing i'
icata :: IFunctor f => (forall i. f a i -> a i) -> (forall i. IFix f i -> a i)
icata f = f . imap (icata f) . unIFix
instance IEq1 f => IEq (IFix f) where
IFix a `ieq` IFix b = a `ieq1` b
instance IEq1 f => Eq (IFix f i) where
IFix a == IFix b = a `ieq1` b
instance (IFunctor f, IShow f) => Show (IFix f i) where
show = getConst . icata ishow