module Type.Class.Witness
( module Type.Class.Witness
, module Exports
) where
import Type.Class.Known
import Type.Family.Constraint
import Data.Type.Equality as Exports
import Data.Void as Exports hiding (absurd)
import qualified Data.Void as Void
import Prelude hiding (id,(.))
import Control.Category
import Control.Arrow
import Unsafe.Coerce
data Wit :: Constraint -> * where
Wit :: c => Wit c
data Wit1 :: (k -> Constraint) -> k -> * where
Wit1 :: c a => Wit1 c a
data (:-) :: Constraint -> Constraint -> * where
Sub :: { getSub :: p => Wit q } -> p :- q
infixr 4 :-
instance Category (:-) where
id = Sub Wit
Sub bc . Sub ab = Sub $ bc \\ ab
transC :: (b :- c) -> (a :- b) -> a :- c
transC = (.)
class WitnessC p q t => Witness (p :: Constraint) (q :: Constraint) (t :: *) | t -> p q where
type WitnessC p q t :: Constraint
type WitnessC p q t = ØC
(\\) :: p => (q => r) -> t -> r
infixl 1 \\
(//) :: (Witness p q t, p) => t -> (q => r) -> r
t // r = r \\ t
infixr 0 //
witnessed :: Witness ØC q t => t -> Wit q
witnessed t = Wit \\ t
entailed :: Witness p q t => t -> p :- q
entailed t = Sub (Wit \\ t)
class Fails (c :: Constraint) where
failC :: c :- Fail
absurdC :: Fails a => a :- b
absurdC = contraC failC
class c => Const (c :: Constraint) (d :: k) where
constC :: Wit c
instance c => Const c d where
constC = Wit
class f (g a) => (∘) (f :: l -> Constraint) (g :: k -> l) (a :: k) where
compC :: Wit (f (g a))
instance f (g a) => (f ∘ g) a where
compC = Wit
infixr 9 ∘
class (f a,g a) => (∧) (f :: k -> Constraint) (g :: k -> Constraint) (a :: k) where
conjC :: (Wit (f a),Wit (g a))
infixr 7 ∧
instance (f a,g a) => (f ∧ g) a where
conjC = (Wit,Wit)
class (∨) (f :: k -> Constraint) (g :: k -> Constraint) (a :: k) where
disjC :: Either (Wit (f a)) (Wit (g a))
infixr 6 ∨
eitherC :: forall f g a b. f a :- b -> g a :- b -> (f ∨ g) a :- b
eitherC f g = Sub $ case (disjC :: Either (Wit (f a)) (Wit (g a)),f,g) of
(Left a,Sub b,_ ) -> b \\ a
(Right a,_ ,Sub b) -> b \\ a
pureC :: b => a :- b
pureC = Sub Wit
contraC :: a :- Fail -> a :- b
contraC = (bottom .)
class Forall (p :: k -> Constraint) (q :: k -> Constraint) where
forall :: p a :- q a
default forall :: q a => p a :- q a
forall = pureC
toEquality :: (a ~ b) :- (c ~ d) -> a :~: b -> c :~: d
toEquality p Refl = Refl \\ p
commute :: (a ~ b) :- (b ~ a)
commute = Sub Wit
type family Holds (b :: Bool) (c :: Constraint) :: Constraint where
Holds True c = c
Holds False c = ØC
falso :: (b ~ False) :- Holds b c
falso = Sub Wit
top :: a :- ØC
top = Sub Wit
bottom :: Fail :- c
bottom = falso
instance Witness ØC c (Wit c) where
r \\ Wit = r
instance Witness ØC (c a) (Wit1 c a) where
r \\ Wit1 = r
instance Witness p q (p :- q) where
r \\ Sub Wit = r
instance Witness ØC (a ~ b) (a :~: b) where
r \\ Refl = r
instance c => Known Wit c where
type KnownC Wit c = c
known = Wit
instance c a => Known (Wit1 c) a where
type KnownC (Wit1 c) a = c a
known = Wit1
(//?) :: (Witness p q t, p) => Maybe t -> (q => Maybe r) -> Maybe r
(//?) = \case
Just t -> (\\ t)
_ -> \_ -> Nothing
infixr 0 //?
(//?+) :: (Witness p q t, p) => Either e t -> (q => Either e r) -> Either e r
(//?+) = \case
Left e -> \_ -> Left e
Right t -> (\\ t)
infixr 0 //?+
witMaybe :: (Witness p q t, p) => Maybe t -> (q => Maybe r) -> Maybe r -> Maybe r
witMaybe mt y n = case mt of
Just t -> y \\ t
_ -> n
qed :: Maybe (a :~: a)
qed = Just Refl
impossible :: a -> Void
impossible = unsafeCoerce
exFalso :: Wit Fail -> a
exFalso p = castWith q ()
where
q :: () :~: a
q = toEquality (contraC r) Refl
r :: (b ~ b) :- Fail
r = Sub p
(=?=) :: TestEquality f => f a -> f b -> Maybe (a :~: b)
(=?=) = testEquality
infix 4 =?=
class TestEquality1 (f :: k -> l -> *) where
testEquality1 :: f a c -> f b c -> Maybe (a :~: b)
(=??=) :: TestEquality1 f => f a c -> f b c -> Maybe (a :~: b)
(=??=) = testEquality1
infix 4 =??=
data Dec a
= Proven a
| Refuted (a -> Void)
class DecEquality (f :: k -> *) where
decideEquality :: f a -> f b -> Dec (a :~: b)
decCase :: Dec a
-> (a -> r)
-> ((a -> Void) -> r)
-> r
decCase d y n = case d of
Proven a -> y a
Refuted b -> n b
absurd :: Arrow p => p Void a
absurd = arr Void.absurd