{-# LANGUAGE TypeOperators, DataKinds, PolyKinds, TypeFamilies,
RankNTypes, FlexibleContexts, TemplateHaskell,
UndecidableInstances, GADTs, DefaultSignatures,
ScopedTypeVariables, TypeApplications #-}
module Data.Singletons.Prelude.Eq (
PEq(..), SEq(..),
DefaultEq,
type (==@#@$), type (==@#@$$), type (==@#@$$$),
type (/=@#@$), type (/=@#@$$), type (/=@#@$$$),
DefaultEqSym0, DefaultEqSym1, DefaultEqSym2
) where
import Data.Singletons.Internal
import Data.Singletons.Prelude.Bool
import Data.Singletons.Single
import Data.Singletons.Prelude.Instances
import Data.Singletons.Util
import Data.Singletons.Promote
import qualified Data.Type.Equality as DTE ()
class PEq a where
type (==) (x :: a) (y :: a) :: Bool
type (/=) (x :: a) (y :: a) :: Bool
type (x :: a) == (y :: a) = x `DefaultEq` y
type (x :: a) /= (y :: a) = Not (x == y)
infix 4 ==
infix 4 /=
type family DefaultEq (a :: k) (b :: k) :: Bool where
DefaultEq a a = 'True
DefaultEq a b = 'False
$(genDefunSymbols [''(==), ''(/=), ''DefaultEq])
class SEq k where
(%==) :: forall (a :: k) (b :: k). Sing a -> Sing b -> Sing (a == b)
infix 4 %==
(%/=) :: forall (a :: k) (b :: k). Sing a -> Sing b -> Sing (a /= b)
default (%/=) :: forall (a :: k) (b :: k).
((a /= b) ~ Not (a == b))
=> Sing a -> Sing b -> Sing (a /= b)
a %/= b = sNot (a %== b)
infix 4 %/=
$(singEqInstances basicTypes)
instance SEq a => SingI ((==@#@$) :: a ~> a ~> Bool) where
sing = singFun2 (%==)
instance (SEq a, SingI x) => SingI ((==@#@$$) x :: a ~> Bool) where
sing = singFun1 (sing @x %==)
instance SEq a => SingI ((/=@#@$) :: a ~> a ~> Bool) where
sing = singFun2 (%/=)
instance (SEq a, SingI x) => SingI ((/=@#@$$) x :: a ~> Bool) where
sing = singFun1 (sing @x %/=)