{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
module Theory.Equality
(
Equals, type (==)
, (==.)
, apply
, substitute
, substituteL
, substituteR
, same
, reflectEq
, propEq
) where
import Data.Arguments
import Data.The
import Theory.Named
import Logic.Proof (Proof, axiom)
import Lawful
import Unsafe.Coerce
import Data.Type.Equality ((:~:)(..))
newtype Equals x y = Equals Defn
type x == y = x `Equals` y
infix 4 ==
instance Argument (Equals x y) 0 where
type GetArg (Equals x y) 0 = x
type SetArg (Equals x y) 0 x' = Equals x' y
instance Argument (Equals x y) 1 where
type GetArg (Equals x y) 1 = y
type SetArg (Equals x y) 1 y' = Equals x y'
instance Argument (Equals x y) LHS where
type GetArg (Equals x y) LHS = x
type SetArg (Equals x y) LHS x' = Equals x' y
instance Argument (Equals x y) RHS where
type GetArg (Equals x y) RHS = y
type SetArg (Equals x y) RHS y' = Equals x y'
(==.) :: Proof (x == y) -> Proof (y == z) -> Proof (x == z)
_ ==. _ = axiom
apply :: forall f n x x'. (Argument f n, GetArg f n ~ x)
=> Arg n -> (x == x') -> Proof (f == SetArg f n x')
apply _ _ = axiom
substitute :: (Argument f n, GetArg f n ~ x)
=> Arg n -> (x == x') -> f -> Proof (SetArg f n x')
substitute _ _ _ = axiom
substituteL :: (Argument f n, GetArg f n ~ x)
=> Arg n -> (x == x') -> (f == g) -> Proof (SetArg f n x' == g)
substituteL _ _ _ = axiom
substituteR :: (Argument f n, GetArg f n ~ x)
=> Arg n -> (x == x') -> (g == f) -> Proof (g == SetArg f n x')
substituteR _ _ _ = axiom
same :: Lawful Eq a => (a ~~ x) -> (a ~~ y) -> Maybe (Proof (x == y))
same (The x) (The y) = if x == y then Just axiom else Nothing
reflectEq :: Proof (x == y) -> (x :~: y)
reflectEq _ = unsafeCoerce (Refl :: a :~: a)
propEq :: (x :~: y) -> Proof (x == y)
propEq _ = axiom