{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
#if MIN_VERSION_base(4,9,0)
{-# LANGUAGE Safe #-}
#else
{-# LANGUAGE Trustworthy #-}
#endif
module Data.Parameterized.Classes
(
Equality.TestEquality(..)
, (Equality.:~:)(..)
, EqF(..)
, PolyEq(..)
, OrdF(..)
, lexCompareF
, OrderingF(..)
, joinOrderingF
, orderingF_refl
, toOrdering
, fromOrdering
, ordFCompose
, ShowF(..)
, showsF
, HashableF(..)
, CoercibleF(..)
, TypeAp(..)
, IndexF
, IxValueF
, IxedF(..)
, IxedF'(..)
, AtF(..)
, KnownRepr(..)
, Data.Hashable.Hashable(..)
, Data.Maybe.isJust
) where
import Data.Functor.Const
import Data.Functor.Compose (Compose(..))
import Data.Kind
import Data.Hashable
import Data.Maybe (isJust)
import Data.Proxy
import Data.Type.Equality as Equality
import Data.Parameterized.Compose ()
type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s
type Traversal' s a = forall f. Applicative f => (a -> f a) -> s -> f s
class CoercibleF (rtp :: k -> *) where
coerceF :: rtp a -> rtp b
instance CoercibleF (Const x) where
coerceF (Const x) = Const x
class EqF (f :: k -> *) where
eqF :: f a -> f a -> Bool
instance Eq a => EqF (Const a) where
eqF (Const x) (Const y) = x == y
class PolyEq u v where
polyEqF :: u -> v -> Maybe (u :~: v)
polyEq :: u -> v -> Bool
polyEq x y = isJust (polyEqF x y)
data OrderingF x y where
LTF :: OrderingF x y
EQF :: OrderingF x x
GTF :: OrderingF x y
orderingF_refl :: OrderingF x y -> Maybe (x :~: y)
orderingF_refl o =
case o of
LTF -> Nothing
EQF -> Just Refl
GTF -> Nothing
toOrdering :: OrderingF x y -> Ordering
toOrdering LTF = LT
toOrdering EQF = EQ
toOrdering GTF = GT
fromOrdering :: Ordering -> OrderingF x x
fromOrdering LT = LTF
fromOrdering EQ = EQF
fromOrdering GT = GTF
joinOrderingF :: forall j k (a :: j) (b :: j) (c :: k) (d :: k)
. OrderingF a b
-> (a ~ b => OrderingF c d)
-> OrderingF c d
joinOrderingF EQF y = y
joinOrderingF LTF _ = LTF
joinOrderingF GTF _ = GTF
class TestEquality ktp => OrdF (ktp :: k -> *) where
{-# MINIMAL compareF #-}
compareF :: ktp x -> ktp y -> OrderingF x y
leqF :: ktp x -> ktp y -> Bool
leqF x y =
case compareF x y of
LTF -> True
EQF -> True
GTF -> False
ltF :: ktp x -> ktp y -> Bool
ltF x y =
case compareF x y of
LTF -> True
EQF -> False
GTF -> False
geqF :: ktp x -> ktp y -> Bool
geqF x y =
case compareF x y of
LTF -> False
EQF -> True
GTF -> True
gtF :: ktp x -> ktp y -> Bool
gtF x y =
case compareF x y of
LTF -> False
EQF -> False
GTF -> True
lexCompareF :: forall j k (f :: j -> *) (a :: j) (b :: j) (c :: k) (d :: k)
. OrdF f
=> f a
-> f b
-> (a ~ b => OrderingF c d)
-> OrderingF c d
lexCompareF x y = joinOrderingF (compareF x y)
ordFCompose :: forall k l (f :: k -> *) (g :: l -> k) x y.
(forall w z. f w -> f z -> OrderingF w z)
-> Compose f g x
-> Compose f g y
-> OrderingF x y
ordFCompose ordF_ (Compose x) (Compose y) =
case ordF_ x y of
LTF -> LTF
GTF -> GTF
EQF -> EQF
instance OrdF f => OrdF (Compose f g) where
compareF x y = ordFCompose compareF x y
class ShowF (f :: k -> *) where
withShow :: p f -> q tp -> (Show (f tp) => a) -> a
default withShow :: Show (f tp) => p f -> q tp -> (Show (f tp) => a) -> a
withShow _ _ x = x
showF :: forall tp . f tp -> String
showF x = withShow (Proxy :: Proxy f) (Proxy :: Proxy tp) (show x)
showsPrecF :: forall tp. Int -> f tp -> String -> String
showsPrecF p x = withShow (Proxy :: Proxy f) (Proxy :: Proxy tp) (showsPrec p x)
showsF :: ShowF f => f tp -> String -> String
showsF x = showsPrecF 0 x
instance Show x => ShowF (Const x)
type family IndexF (m :: *) :: k -> *
type family IxValueF (m :: *) :: k -> *
class IxedF k m where
ixF :: forall (x :: k). IndexF m x -> Traversal' m (IxValueF m x)
class IxedF k m => IxedF' k m where
ixF' :: forall (x :: k). IndexF m x -> Lens' m (IxValueF m x)
class IxedF k m => AtF k m where
atF :: forall (x :: k). IndexF m x -> Lens' m (Maybe (IxValueF m x))
defaultSalt :: Int
#if WORD_SIZE_IN_BITS == 64
defaultSalt = 0xdc36d1615b7400a4
#else
defaultSalt = 0x087fc72c
#endif
{-# INLINE defaultSalt #-}
class HashableF (f :: k -> *) where
hashWithSaltF :: Int -> f tp -> Int
hashF :: f tp -> Int
hashF = hashWithSaltF defaultSalt
instance Hashable a => HashableF (Const a) where
hashWithSaltF s (Const x) = hashWithSalt s x
newtype TypeAp (f :: k -> Type) (tp :: k) = TypeAp (f tp)
instance TestEquality f => Eq (TypeAp f tp) where
TypeAp x == TypeAp y = isJust $ testEquality x y
instance OrdF f => Ord (TypeAp f tp) where
compare (TypeAp x) (TypeAp y) = toOrdering (compareF x y)
instance ShowF f => Show (TypeAp f tp) where
showsPrec p (TypeAp x) = showsPrecF p x
instance HashableF f => Hashable (TypeAp f tp) where
hashWithSalt s (TypeAp x) = hashWithSaltF s x
class KnownRepr (f :: k -> *) (ctx :: k) where
knownRepr :: f ctx