--------------------------------------------------------------------------------
-- Copyright © 2011 National Institute of Aerospace / Galois, Inc.
--------------------------------------------------------------------------------

{-# LANGUAGE Safe #-}
{-# LANGUAGE GADTs, KindSignatures #-}

-- | Propositional equality and type equality.
module Copilot.Core.Type.Equality
  ( Equal (..)
  , EqualType (..)
  , coerce
  , refl
  , trans
  , symm
  , cong
  ) where

-- | Propositional equality.
data Equal :: * -> * -> * where
  Refl :: Equal a a

-- | Type equality. If the value of @x =~= y@ is @Just Refl@, then the two
-- types @x@ and @y@ are equal.
class EqualType t where
  (=~=) :: t a -> t b -> Maybe (Equal a b)

-- | Safe coercion, which requires proof of equality.
coerce :: Equal a b -> a -> b
coerce :: Equal a b -> a -> b
coerce Equal a b
Refl a
x = a
b
x

-- | Proof of propositional equality.
refl :: Equal a a
refl :: Equal a a
refl = Equal a a
forall a. Equal a a
Refl

-- | Symmetry.
symm :: Equal a b -> Equal b a
symm :: Equal a b -> Equal b a
symm Equal a b
Refl = Equal b a
forall a. Equal a a
Refl

-- | Transitivity.
trans :: Equal a b -> Equal b c -> Equal a c
trans :: Equal a b -> Equal b c -> Equal a c
trans Equal a b
Refl Equal b c
Refl = Equal a c
forall a. Equal a a
Refl

-- | Congruence.
cong :: Equal a b -> Equal (f a) (f b)
cong :: Equal a b -> Equal (f a) (f b)
cong Equal a b
Refl = Equal (f a) (f b)
forall a. Equal a a
Refl