datafix-0.0.1.0: src/Datafix/Utils/Constraints.hs
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UndecidableSuperClasses #-}
-- |
-- Module : Datafix.Utils.Constraints
-- Copyright : (c) Sebastian Graf 2017-2020
-- License : ISC
-- Maintainer : sgraf1337@gmail.com
-- Portability : portable
--
-- Universally quantified constraints, until we have -XQuantifiedConstraints.
module Datafix.Utils.Constraints
( Dict (..)
, (:-) (..)
, (\\)
, Forall
, inst
) where
import Data.Kind
import Unsafe.Coerce (unsafeCoerce)
data Dict :: Constraint -> Type where
Dict :: c => Dict c
newtype a :- b = Sub (a => Dict b)
infixl 1 \\ -- required comment
-- | Given that @a :- b@, derive something that needs a context @b@, using the context @a@
(\\) :: a => (b => r) -> (a :- b) -> r
r \\ Sub Dict = r
-- The `Skolem` type family represents skolem variables; do not export!
-- If GHC supports it, these might be made closed with no instances.
type family Skolem (p :: k -> Constraint) :: k
-- The outer `Forall` type family prevents GHC from giving a spurious
-- superclass cycle error.
-- The inner `Forall_` class prevents the skolem from leaking to the user,
-- which would be disastrous.
-- | A representation of the quantified constraint @forall a. p a@.
type family Forall (p :: k -> Constraint) :: Constraint
type instance Forall p = Forall_ p
class p (Skolem p) => Forall_ (p :: k -> Constraint)
instance p (Skolem p) => Forall_ (p :: k -> Constraint)
inst :: forall p a . Forall p :- p a
inst = unsafeCoerce (Sub Dict :: Forall p :- p (Skolem p))