htree-0.1.1.0: src/Data/HTree/Constraint.hs
{-# LANGUAGE UndecidableSuperClasses #-}
-- | A couple of types to work with Constraints
module Data.HTree.Constraint
( -- * proving a constraint
Has (..)
-- ** synonyms for proving a constraint
, HasTypeable
, HasIs
-- ** helpers to work with constraints
, proves
, Charge
-- * Dict
, type Dict
, pattern Dict
-- ** functions for working with 'Dict's
, withDict
)
where
import Data.Kind (Constraint, Type)
import Data.Proxy (Proxy (Proxy))
import Type.Reflection (Typeable)
-- | a functor useful for proving a constraint for some type
--
-- >>> import Data.Functor.Identity
-- >>> Proves @Eq (Identity (5 :: Int))
-- Proves (Identity 5)
type Has :: forall k. (k -> Constraint) -> (k -> Type) -> k -> Type
data Has c f k where
Proves :: c k => f k -> Has c f k
-- | transform a 'Constraint' in something of kind @k -> 'Constraint'@ to be
-- able to use it in 'Has'
type Charge :: Constraint -> k -> Constraint
class c => Charge c a
instance c => Charge c a
-- | a Dict witnesses some constraint
type Dict :: Constraint -> Type
type Dict c = Has (Charge c) Proxy ()
-- | match on a 'Dict'
pattern Dict :: forall (c :: Constraint). forall. c => Dict c
pattern Dict = Proves Proxy
{-# COMPLETE Dict #-}
-- | destructing a 'Dict'
withDict :: Dict c -> (c => r) -> r
withDict d k = proves d (const k)
-- | destruct a 'Has'
proves :: Has c f a -> (c a => f a -> r) -> r
proves (Proves x) k = k x
-- | 'Has' but specialised to 'Typeable'
type HasTypeable :: (k -> Type) -> k -> Type
type HasTypeable = Has Typeable
-- | 'Has' but specialised to a constant type, @Some (HasIs k f)@ is isomorphic to @f k@
type HasIs :: k -> (k -> Type) -> k -> Type
type HasIs k = Has ((~) k)
deriving stock instance Show (f k) => Show (Has c f k)