darcs-2.18.1: src/Darcs/Patch/Witnesses/Eq.hs
module Darcs.Patch.Witnesses.Eq
( EqCheck(..)
, Eq2(..)
, isIsEq
) where
import Darcs.Prelude
import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP )
-- |'EqCheck' is used to pass around evidence (or lack thereof) of
-- two witness types being equal.
data EqCheck wA wB where
IsEq :: EqCheck wA wA
NotEq :: EqCheck wA wB
instance Eq (EqCheck wA wB) where
IsEq == IsEq = True
NotEq == NotEq = True
_ == _ = False
instance Show (EqCheck wA wB) where
show IsEq = "IsEq"
show NotEq = "NotEq"
-- |An witness aware equality class.
-- A minimal definition defines any one of 'unsafeCompare', '=\/=' and '=/\='.
class Eq2 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 wA wB -> p wC wD -> 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 wA wB -> p wA wC -> EqCheck wB wC
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 wA wC -> p wB wC -> EqCheck wA wB
a =/\= b | IsEq == (a =\/= unsafeCoerceP b) = unsafeCoerceP IsEq
| otherwise = NotEq
{-# MINIMAL unsafeCompare | (=\/=) | (=/\=) #-}
infix 4 =\/=, =/\=
isIsEq :: EqCheck wA wB -> Bool
isIsEq IsEq = True
isIsEq NotEq = False