{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Data.HDiff.MetaVar where
import Data.Function (on)
import Data.Functor.Const
import Data.Type.Equality
import Generics.MRSOP.Util
import Generics.MRSOP.Base
import Data.Exists
import Generics.MRSOP.HDiff.Digest
import Generics.MRSOP.HDiff.Holes
data ForceI :: (Nat -> *) -> Atom kon -> * where
ForceI :: (IsNat i) => { unForceI :: f i } -> ForceI f ('I i)
type MetaVarI = ForceI (Const Int)
data Annotate (x :: *) (f :: k -> *) :: k -> * where
Annotate :: x -> f i -> Annotate x f i
instance (ShowHO f , Show x) => Show (Annotate x f k) where
show (Annotate i f)
= show f ++ "[" ++ show i ++ "]"
instance (EqHO f , Eq x) => Eq (Annotate x f k) where
(==) (Annotate x1 f1) (Annotate x2 f2) = x1 == x2 && f1 == f2
instance (TestEquality ki) => TestEquality (Annotate x ki) where
testEquality (Annotate _ x) (Annotate _ y)
= testEquality x y
type MetaVarIK ki = NA (Annotate Int ki) (Const Int)
instance (DigestibleHO ki) => DigestibleHO (MetaVarIK ki) where
digestHO (NA_I (Const i)) = hashStr ("vari" ++ show i)
digestHO (NA_K (Annotate i _)) = hashStr ("vark" ++ show i)
metavarGet :: MetaVarIK ki at -> Int
metavarGet = elimNA go getConst
where go (Annotate x _) = x
metavarAdd :: Int -> MetaVarIK ki at -> MetaVarIK ki at
metavarAdd n (NA_K (Annotate i x)) = NA_K $ Annotate (n + i) x
metavarAdd n (NA_I (Const i)) = NA_I $ Const (n + i)
instance HasIKProjInj ki (MetaVarIK ki) where
konInj k = NA_K (Annotate 0 k)
varProj _ (NA_I _) = Just IsI
varProj _ _ = Nothing
metavarIK2Int :: Exists (MetaVarIK ki) -> Int
metavarIK2Int (Exists (NA_I (Const i))) = i
metavarIK2Int (Exists (NA_K (Annotate i _))) = i
metavarI2Int :: Exists MetaVarI -> Int
metavarI2Int (Exists (ForceI (Const i))) = i
metavarI2IK :: MetaVarI ix -> MetaVarIK ki ix
metavarI2IK (ForceI x) = NA_I x
instance Eq (Exists MetaVarI) where
(==) = (==) `on` metavarI2Int
instance Ord (Exists MetaVarI) where
compare = compare `on` metavarI2Int
instance Eq (Exists (MetaVarIK ki)) where
(==) = (==) `on` metavarIK2Int
instance Ord (Exists (MetaVarIK ki)) where
compare = compare `on` metavarIK2Int