{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExplicitNamespaces #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UndecidableSuperClasses #-}
module Type.Membership
(
Membership
, getMemberId
, mkMembership
, leadership
, nextMembership
, testMembership
, compareMembership
, impossibleMembership
, reifyMembership
, Member
, Assoc(..)
, type (>:)
, Lookup(..)
, KeyOf
, KeyIs
, proxyKeyOf
, stringKeyOf
, TargetOf
, proxyTargetOf
, TargetIs
, KeyTargetAre
, Generate(..)
, Forall(..)
, ForallF
, Proxy(..)
) where
import Data.Constraint
import Data.Proxy
import Data.String
import GHC.TypeLits
import Type.Membership.Internal
class Generate (xs :: [k]) where
henumerate :: (forall x. Membership xs x -> r -> r) -> r -> r
hcount :: proxy xs -> Int
hgenerateList :: Applicative f
=> (forall x. Membership xs x -> f (h x)) -> f (HList h xs)
instance Generate '[] where
henumerate _ r = r
hcount _ = 0
hgenerateList _ = pure HNil
instance Generate xs => Generate (x ': xs) where
henumerate f r = f leadership $ henumerate (f . nextMembership) r
hcount _ = 1 + hcount (Proxy :: Proxy xs)
hgenerateList f = HCons <$> f leadership <*> hgenerateList (f . nextMembership)
class (ForallF c xs, Generate xs) => Forall (c :: k -> Constraint) (xs :: [k]) where
henumerateFor :: proxy c -> proxy' xs -> (forall x. c x => Membership xs x -> r -> r) -> r -> r
hgenerateListFor :: Applicative f
=> proxy c -> (forall x. c x => Membership xs x -> f (h x)) -> f (HList h xs)
instance Forall c '[] where
henumerateFor _ _ _ r = r
hgenerateListFor _ _ = pure HNil
instance (c x, Forall c xs) => Forall c (x ': xs) where
henumerateFor p _ f r = f leadership $ henumerateFor p (Proxy :: Proxy xs) (f . nextMembership) r
hgenerateListFor p f = HCons <$> f leadership <*> hgenerateListFor p (f . nextMembership)
type family ForallF (c :: k -> Constraint) (xs :: [k]) :: Constraint where
ForallF c '[] = ()
ForallF c (x ': xs) = (c x, Forall c xs)
type family KeyOf (kv :: Assoc k v) :: k where
KeyOf (k ':> v) = k
proxyKeyOf :: proxy kv -> Proxy (KeyOf kv)
proxyKeyOf _ = Proxy
stringKeyOf :: (IsString a, KnownSymbol (KeyOf kv)) => proxy kv -> a
stringKeyOf = fromString . symbolVal . proxyKeyOf
{-# INLINE stringKeyOf #-}
class (pk (KeyOf kv)) => KeyIs pk kv where
instance (pk k) => KeyIs pk (k ':> v)
type family TargetOf (kv :: Assoc k v) :: v where
TargetOf (k ':> v) = v
proxyTargetOf :: proxy kv -> Proxy (TargetOf kv)
proxyTargetOf _ = Proxy
class (pv (TargetOf kv)) => TargetIs pv kv where
instance (pv v) => TargetIs pv (k ':> v)
class (pk (KeyOf kv), pv (TargetOf kv)) => KeyTargetAre pk pv kv where
instance (pk k, pv v) => KeyTargetAre pk pv (k ':> v)