{-# LANGUAGE
AllowAmbiguousTypes,
ConstraintKinds,
DataKinds,
PolyKinds,
RankNTypes,
TypeFamilies,
TypeInType,
TypeOperators #-}
module Fcf.Utils
( Error
, TError
, Constraints
, TyEq
, Stuck
, IsBool(_If)
, If
) where
import Data.Kind (Constraint)
import Data.Type.Bool (If)
import GHC.TypeLits (Symbol, TypeError, ErrorMessage(..))
import Fcf.Core
data Error :: Symbol -> Exp a
type instance Eval (Error msg) = TypeError ('Text msg)
data TError :: ErrorMessage -> Exp a
type instance Eval (TError msg) = TypeError msg
data Constraints :: [Constraint] -> Exp Constraint
type instance Eval (Constraints '[]) = (() :: Constraint)
type instance Eval (Constraints (a ': as)) = (a, Eval (Constraints as))
data TyEq :: a -> b -> Exp Bool
type instance Eval (TyEq a b) = TyEqImpl a b
type family TyEqImpl (a :: k) (b :: k) :: Bool where
TyEqImpl a a = 'True
TyEqImpl a b = 'False
type family Stuck :: a
class IsBool (b :: Bool) where
_If :: ((b ~ 'True) => r) -> ((b ~ 'False) => r) -> r
instance IsBool 'True where _If a _ = a
instance IsBool 'False where _If _ b = b