darcs-2.8.0: src/Darcs/Witnesses/Eq.hs
#include "gadts.h"
module Darcs.Witnesses.Eq (
EqCheck(..), MyEq(..), isIsEq
) where
import Darcs.Witnesses.Unsafe ( unsafeCoerceP )
-- |'EqCheck' is used to pass around evidence (or lack thereof) of
-- two witness types being equal.
data EqCheck C(a b) where
IsEq :: EqCheck C(a a)
NotEq :: EqCheck C(a b)
instance Eq (EqCheck C(a b)) where
IsEq == IsEq = True
NotEq == NotEq = True
_ == _ = False
instance Show (EqCheck C(a b)) where
show IsEq = "IsEq"
show NotEq = "NotEq"
-- |An witness aware equality class.
-- A minimal definition defines any one of 'unsafeCompare', '=\/=' and '=/\='.
class MyEq p where
-- |It is unsafe to define a class instance via this method, because
-- if it returns True then the default implementations of '=\/=' and '=/\='
-- will coerce the equality of two witnesses.
--
-- Calling this method is safe, although '=\/=' or '=/\=' would be better
-- choices as it is not usually meaningul to compare two patches that
-- don't share either a starting or an ending context
unsafeCompare :: p C(a b) -> p C(c d) -> Bool
unsafeCompare a b = IsEq == (a =/\= unsafeCoerceP b)
-- |Compare two things with the same starting witness. If the things
-- compare equal, evidence of the ending witnesses being equal will
-- be returned.
(=\/=) :: p C(a b) -> p C(a c) -> EqCheck C(b c)
a =\/= b | unsafeCompare a b = unsafeCoerceP IsEq
| otherwise = NotEq
-- |Compare two things with the same ending witness. If the things
-- compare equal, evidence of the starting witnesses being equal will
-- be returned.
(=/\=) :: p C(a c) -> p C(b c) -> EqCheck C(a b)
a =/\= b | IsEq == (a =\/= unsafeCoerceP b) = unsafeCoerceP IsEq
| otherwise = NotEq
infix 4 =\/=, =/\=
isIsEq :: EqCheck C(a b) -> Bool
isIsEq IsEq = True
isIsEq NotEq = False