{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE TypeOperators #-}
module Data.Type.Role.Phantom
( Phantom
, Phantomicity(..)
, applyPhantom
, NonPhantom
, NonPhantomicity(..)
, innerNonPhantom
) where
import Data.Coerce
import Data.Type.Coercion
import Data.Type.Role.Nominal
import Data.Type.Equality ((:~:)(..))
class (forall a b. Coercible (f a) (f b)) => Phantom (f :: k -> l)
instance (forall a b. Coercible (f a) (f b)) => Phantom f
data Phantomicity (f :: k -> l) where
Phantomicity :: Phantom f => Phantomicity f
applyPhantom :: Phantomicity f -> Coercion f g -> Coercion (f a) (g b)
applyPhantom Phantomicity k@Coercion = Coercion `trans` applyNominal k Refl
applyPhantom' :: Phantomicity g -> Coercion f g -> Coercion (f a) (g b)
applyPhantom' Phantomicity k@Coercion = applyNominal k Refl `trans` Coercion
class (forall a b. Coercible (f a) (f b) => Coercible a b)
=> NonPhantom (f :: k -> l)
instance (forall a b. Coercible (f a) (f b) => Coercible a b)
=> NonPhantom f
data NonPhantomicity (f :: k -> l) where
NonPhantomicity :: NonPhantom f => NonPhantomicity f
innerNonPhantom :: NonPhantomicity f -> Coercion (f a) (f b) -> Coercion a b
innerNonPhantom NonPhantomicity Coercion = Coercion