{-# LANGUAGE TypeOperators, KindSignatures, DataKinds, PolyKinds,
TypeFamilies, UndecidableInstances, EmptyDataDecls,
MultiParamTypeClasses, FlexibleInstances, ConstraintKinds #-}
module Data.GI.Base.Overloading
(
ParentTypes
, HasParentTypes
, IsDescendantOf
, AttributeList
, HasAttributeList
, ResolveAttribute
, HasAttribute
, HasAttr
, SignalList
, ResolveSignal
, HasSignal
, MethodInfo(..)
, MethodProxy(..)
, MethodResolutionFailed
) where
import GHC.Exts (Constraint)
import GHC.TypeLits
type family FindElement (m :: Symbol) (ms :: [(Symbol, *)])
(typeError :: ErrorMessage) :: * where
FindElement m '[] typeError = TypeError typeError
FindElement m ('(m, o) ': ms) typeError = o
FindElement m ('(m', o) ': ms) typeError = FindElement m ms typeError
type family CheckForAncestorType t (a :: *) (as :: [*]) :: Constraint where
CheckForAncestorType t a '[] = TypeError ('Text "Required ancestor ‘"
':<>: 'ShowType a
':<>: 'Text "’ not found for type ‘"
':<>: 'ShowType t ':<>: 'Text "’.")
CheckForAncestorType t a (a ': as) = ()
CheckForAncestorType t a (b ': as) = CheckForAncestorType t a as
type family IsDescendantOf (parent :: *) (descendant :: *) :: Constraint where
IsDescendantOf d d = ()
IsDescendantOf p d = CheckForAncestorType d p (ParentTypes d)
type family ParentTypes a :: [*]
class HasParentTypes o
instance {-# OVERLAPPABLE #-}
TypeError ('Text "Type ‘" ':<>: 'ShowType a ':<>:
'Text "’ does not have any known parent types.")
=> HasParentTypes a
type family AttributeList a :: [(Symbol, *)]
class HasAttributeList a
instance {-# OVERLAPPABLE #-}
TypeError ('Text "Type ‘" ':<>: 'ShowType a ':<>:
'Text "’ does not have any known attributes.")
=> HasAttributeList a
type family ResolveAttribute (s :: Symbol) (o :: *) :: * where
ResolveAttribute s o = FindElement s (AttributeList o)
('Text "Unknown attribute ‘" ':<>:
'Text s ':<>: 'Text "’ for object ‘" ':<>:
'ShowType o ':<>: 'Text "’.")
type family IsElem (e :: Symbol) (es :: [(Symbol, *)]) (success :: k)
(failure :: ErrorMessage) :: k where
IsElem e '[] success failure = TypeError failure
IsElem e ( '(e, t) ': es) success failure = success
IsElem e ( '(other, t) ': es) s f = IsElem e es s f
type family HasAttribute (attr :: Symbol) (o :: *) :: Constraint where
HasAttribute attr o = IsElem attr (AttributeList o)
(() :: Constraint)
('Text "Attribute ‘" ':<>: 'Text attr ':<>:
'Text "’ not found for type ‘" ':<>:
'ShowType o ':<>: 'Text "’.")
class HasAttr (attr :: Symbol) (o :: *)
instance HasAttribute attr o => HasAttr attr o
type family SignalList a :: [(Symbol, *)]
type family ResolveSignal (s :: Symbol) (o :: *) :: * where
ResolveSignal s o = FindElement s (SignalList o)
('Text "Unknown signal ‘" ':<>:
'Text s ':<>: 'Text "’ for object ‘" ':<>:
'ShowType o ':<>: 'Text "’.")
type family HasSignal (s :: Symbol) (o :: *) :: Constraint where
HasSignal s o = IsElem s (SignalList o)
(() :: Constraint)
('Text "Signal ‘" ':<>: 'Text s ':<>:
'Text "’ not found for type ‘" ':<>:
'ShowType o ':<>: 'Text "’.")
class MethodInfo i o s where
overloadedMethod :: MethodProxy i -> o -> s
data MethodProxy a = MethodProxy
type family MethodResolutionFailed (method :: Symbol) (o :: *) where
MethodResolutionFailed m o =
TypeError ('Text "Unknown method ‘" ':<>:
'Text m ':<>: 'Text "’ for type ‘" ':<>:
'ShowType o ':<>: 'Text "’.")