{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Type.Predicate.Param (
ParamPred
, IsTC, EqBy
, FlipPP, ConstPP, PPMap, PPMapV, InP, AnyMatch, TyPP
, Found, NotFound
, Selectable, select
, Searchable, search
, inPNotNull, notNullInP
, SelectableTC, selectTC
, SearchableTC, searchTC
, OrP, AndP
) where
import Data.Kind
import Data.Singletons
import Data.Singletons.Decide
import Data.Singletons.Prelude.Tuple
import Data.Singletons.Sigma
import Data.Type.Functor.Product
import Data.Type.Predicate
import Data.Type.Predicate.Logic
import Data.Type.Universe
type ParamPred k v = k -> Predicate v
data Found :: ParamPred k v -> Predicate k
type instance Apply (Found (p :: ParamPred k v)) a = Σ v (p a)
type NotFound (p :: ParamPred k v) = (Not (Found p) :: Predicate k)
data FlipPP :: ParamPred v k -> ParamPred k v
type instance Apply (FlipPP p x) y = p y @@ x
data ConstPP :: Predicate v -> ParamPred k v
type instance Apply (ConstPP p k) v = p @@ v
data EqBy :: (v ~> k) -> ParamPred k v
type instance Apply (EqBy f x) y = x :~: (f @@ y)
type IsTC t = EqBy (TyCon1 t)
data TyPP :: (k -> v -> Type) -> ParamPred k v
type instance Apply (TyPP t k) v = t k v
data PPMap :: (k ~> j) -> ParamPred j v -> ParamPred k v
type instance Apply (PPMap f p x) y = p (f @@ x) @@ y
data PPMapV :: (u ~> v) -> ParamPred k u -> ParamPred k v
type instance Apply (PPMapV f p x) y = p x @@ (f @@ y)
instance (Decidable (Found (p :: ParamPred j v)), SingI (f :: k ~> j)) => Decidable (Found (PPMap f p)) where
decide :: Sing a -> Decision (Found (PPMap f p) @@ a)
decide = (Sigma v (p (Apply f a)) -> Sigma v (PPMap f p a))
-> (Sigma v (PPMap f p a) -> Sigma v (p (Apply f a)))
-> Decision (Sigma v (p (Apply f a)))
-> Decision (Sigma v (PPMap f p a))
forall a b. (a -> b) -> (b -> a) -> Decision a -> Decision b
mapDecision (\case i :: Sing fst
i :&: p :: p (Apply f a) @@ fst
p -> Sing fst
i Sing fst -> (PPMap f p a @@ fst) -> Sigma v (PPMap f p a)
forall s (a :: s ~> *) (fst :: s).
Sing fst -> (a @@ fst) -> Sigma s a
:&: p (Apply f a) @@ fst
PPMap f p a @@ fst
p)
(\case i :: Sing fst
i :&: p :: PPMap f p a @@ fst
p -> Sing fst
i Sing fst -> (p (Apply f a) @@ fst) -> Sigma v (p (Apply f a))
forall s (a :: s ~> *) (fst :: s).
Sing fst -> (a @@ fst) -> Sigma s a
:&: p (Apply f a) @@ fst
PPMap f p a @@ fst
p)
(Decision (Sigma v (p (Apply f a)))
-> Decision (Sigma v (PPMap f p a)))
-> (Sing a -> Decision (Sigma v (p (Apply f a))))
-> Sing a
-> Decision (Sigma v (PPMap f p a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Decidable (Found p) => Decide (Found p)
forall k1 (p :: k1 ~> *). Decidable p => Decide p
decide @(Found p)
(Sing (Apply f a) -> Decision (Sigma v (p (Apply f a))))
-> (Sing a -> Sing (Apply f a))
-> Sing a
-> Decision (Sigma v (p (Apply f a)))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SLambda f -> forall (t :: k). Sing t -> Sing (f @@ t)
forall k1 k2 (f :: k1 ~> k2).
SLambda f -> forall (t :: k1). Sing t -> Sing (f @@ t)
applySing (Sing f
forall k (a :: k). SingI a => Sing a
sing :: Sing f)
instance (Provable (Found (p :: ParamPred j v)), SingI (f :: k ~> j)) => Provable (Found (PPMap f p)) where
prove :: Sing a -> Found (PPMap f p) @@ a
prove (x :: Sing a) = case Sing (Apply f a) -> Found p @@ Apply f a
forall k1 (p :: k1 ~> *). Provable p => Prove p
prove @(Found p) ((Sing f
forall k (a :: k). SingI a => Sing a
sing :: Sing f) Sing f -> Sing a -> Sing (Apply f a)
forall k1 k2 (f :: k1 ~> k2) (t :: k1).
Sing f -> Sing t -> Sing (f @@ t)
@@ Sing a
x) of
i :&: p -> Sing fst
i Sing fst -> (PPMap f p a @@ fst) -> Sigma v (PPMap f p a)
forall s (a :: s ~> *) (fst :: s).
Sing fst -> (a @@ fst) -> Sigma s a
:&: p (Apply f a) @@ fst
PPMap f p a @@ fst
p
type Searchable p = Decidable (Found p)
type Selectable p = Provable (Found p)
search
:: forall p. Searchable p
=> Decide (Found p)
search :: Decide (Found p)
search = Decidable (Found p) => Decide (Found p)
forall k1 (p :: k1 ~> *). Decidable p => Decide p
decide @(Found p)
select
:: forall p. Selectable p
=> Prove (Found p)
select :: Prove (Found p)
select = Provable (Found p) => Prove (Found p)
forall k1 (p :: k1 ~> *). Provable p => Prove p
prove @(Found p)
type SearchableTC t = Decidable (Found (TyPP t))
type SelectableTC t = Provable (Found (TyPP t))
searchTC
:: forall t. SearchableTC t
=> Decide (Found (TyPP t))
searchTC :: Decide (Found (TyPP t))
searchTC = Searchable (TyPP t) => Decide (Found (TyPP t))
forall k1 v (p :: ParamPred k1 v). Searchable p => Decide (Found p)
search @(TyPP t)
selectTC
:: forall t. SelectableTC t
=> Prove (Found (TyPP t))
selectTC :: Prove (Found (TyPP t))
selectTC = Selectable (TyPP t) => Prove (Found (TyPP t))
forall k1 v (p :: ParamPred k1 v). Selectable p => Prove (Found p)
select @(TyPP t)
type InP f = (ElemSym1 f :: ParamPred (f k) k)
notNullInP :: NotNull f --> Found (InP f)
notNullInP :: Sing a -> (NotNull f @@ a) -> Found (InP f) @@ a
notNullInP _ (WitAny i s) = Sing a
Evident @@ a
s Sing a -> (ElemSym1 f a @@ a) -> Sigma k (ElemSym1 f a)
forall s (a :: s ~> *) (fst :: s).
Sing fst -> (a @@ fst) -> Sigma s a
:&: Elem f a a
ElemSym1 f a @@ a
i
inPNotNull :: Found (InP f) --> NotNull f
inPNotNull :: Sing a -> (Found (InP f) @@ a) -> NotNull f @@ a
inPNotNull _ (s :&: i) = Elem f a fst -> (Evident @@ fst) -> WitAny f Evident a
forall k (f :: * -> *) (as :: f k) (a :: k) (p :: k ~> *).
Elem f as a -> (p @@ a) -> WitAny f p as
WitAny Elem f a fst
ElemSym1 f a @@ fst
i Sing fst
Evident @@ fst
s
instance Universe f => Decidable (Found (InP f)) where
decide :: Sing a -> Decision (Found (InP f) @@ a)
decide = (WitAny f Evident a -> Sigma v (ElemSym1 f a))
-> (Sigma v (ElemSym1 f a) -> WitAny f Evident a)
-> Decision (WitAny f Evident a)
-> Decision (Sigma v (ElemSym1 f a))
forall a b. (a -> b) -> (b -> a) -> Decision a -> Decision b
mapDecision (\case WitAny i :: Elem f a a
i s :: Evident @@ a
s -> Sing a
Evident @@ a
s Sing a -> (ElemSym1 f a @@ a) -> Sigma v (ElemSym1 f a)
forall s (a :: s ~> *) (fst :: s).
Sing fst -> (a @@ fst) -> Sigma s a
:&: Elem f a a
ElemSym1 f a @@ a
i )
(\case s :: Sing fst
s :&: i :: ElemSym1 f a @@ fst
i -> Elem f a fst -> (Evident @@ fst) -> WitAny f Evident a
forall k (f :: * -> *) (as :: f k) (a :: k) (p :: k ~> *).
Elem f as a -> (p @@ a) -> WitAny f p as
WitAny Elem f a fst
ElemSym1 f a @@ fst
i Sing fst
Evident @@ fst
s)
(Decision (WitAny f Evident a)
-> Decision (Sigma v (ElemSym1 f a)))
-> (Sing a -> Decision (WitAny f Evident a))
-> Sing a
-> Decision (Sigma v (ElemSym1 f a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Decidable (NotNull f) => Decide (NotNull f)
forall k1 (p :: k1 ~> *). Decidable p => Decide p
decide @(NotNull f)
instance Decidable (NotNull f ==> Found (InP f))
instance Provable (NotNull f ==> Found (InP f)) where
prove :: Sing a -> (NotNull f ==> Found (InP f)) @@ a
prove = Sing a -> (NotNull f ==> Found (InP f)) @@ a
forall k (f :: * -> *). NotNull f --> Found (InP f)
notNullInP
instance Decidable (Found (InP f) ==> NotNull f)
instance Provable (Found (InP f) ==> NotNull f) where
prove :: Sing a -> (Found (InP f) ==> NotNull f) @@ a
prove = Sing a -> (Found (InP f) ==> NotNull f) @@ a
forall v (f :: * -> *). Found (InP f) --> NotNull f
inPNotNull
data AnyMatch f :: ParamPred k v -> ParamPred (f k) v
type instance Apply (AnyMatch f p as) a = Any f (FlipPP p a) @@ as
instance (Universe f, Decidable (Found p)) => Decidable (Found (AnyMatch f p)) where
decide :: Sing a -> Decision (Found (AnyMatch f p) @@ a)
decide = (WitAny f (Found p) a -> Sigma v (AnyMatch f p a))
-> (Sigma v (AnyMatch f p a) -> WitAny f (Found p) a)
-> Decision (WitAny f (Found p) a)
-> Decision (Sigma v (AnyMatch f p a))
forall a b. (a -> b) -> (b -> a) -> Decision a -> Decision b
mapDecision (\case WitAny i :: Elem f a a
i (x :&: p) -> Sing fst
x Sing fst -> (AnyMatch f p a @@ fst) -> Sigma v (AnyMatch f p a)
forall s (a :: s ~> *) (fst :: s).
Sing fst -> (a @@ fst) -> Sigma s a
:&: Elem f a a -> (FlipPP p fst @@ a) -> WitAny f (FlipPP p fst) a
forall k (f :: * -> *) (as :: f k) (a :: k) (p :: k ~> *).
Elem f as a -> (p @@ a) -> WitAny f p as
WitAny Elem f a a
i FlipPP p fst @@ a
p a @@ fst
p )
(\case x :: Sing fst
x :&: WitAny i p -> Elem f a a -> (Found p @@ a) -> WitAny f (Found p) a
forall k (f :: * -> *) (as :: f k) (a :: k) (p :: k ~> *).
Elem f as a -> (p @@ a) -> WitAny f p as
WitAny Elem f a a
i (Sing fst
x Sing fst -> (p a @@ fst) -> Sigma v (p a)
forall s (a :: s ~> *) (fst :: s).
Sing fst -> (a @@ fst) -> Sigma s a
:&: FlipPP p fst @@ a
p a @@ fst
p))
(Decision (WitAny f (Found p) a)
-> Decision (Sigma v (AnyMatch f p a)))
-> (Sing a -> Decision (WitAny f (Found p) a))
-> Sing a
-> Decision (Sigma v (AnyMatch f p a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Decidable (Any f (Found p)) => Decide (Any f (Found p))
forall k1 (p :: k1 ~> *). Decidable p => Decide p
decide @(Any f (Found p))
data OrP :: ParamPred k v -> ParamPred k v -> ParamPred k v
type instance Apply (OrP p q x) y = (p x ||| q x) @@ y
data AndP :: ParamPred k v -> ParamPred k u -> ParamPred k (v, u)
type instance Apply (AndP p q x) '(y, z) = (p x @@ y, q x @@ z)
instance (Searchable p, Searchable q) => Decidable (Found (OrP p q)) where
decide :: Sing a -> Decision (Found (OrP p q) @@ a)
decide x :: Sing a
x = case Sing a -> Decision (Found p @@ a)
forall k1 v (p :: ParamPred k1 v). Searchable p => Decide (Found p)
search @p Sing a
x of
Proved (s :&: p) -> Sigma v (OrP p q a) -> Decision (Found (OrP p q) @@ a)
forall a. a -> Decision a
Proved (Sigma v (OrP p q a) -> Decision (Found (OrP p q) @@ a))
-> Sigma v (OrP p q a) -> Decision (Found (OrP p q) @@ a)
forall a b. (a -> b) -> a -> b
$ Sing fst
s Sing fst -> (OrP p q a @@ fst) -> Sigma v (OrP p q a)
forall s (a :: s ~> *) (fst :: s).
Sing fst -> (a @@ fst) -> Sigma s a
:&: Apply (p a) fst -> Either (Apply (p a) fst) (Apply (q a) fst)
forall a b. a -> Either a b
Left Apply (p a) fst
p
Disproved vp :: Refuted (Found p @@ a)
vp -> case Sing a -> Decision (Found q @@ a)
forall k1 v (p :: ParamPred k1 v). Searchable p => Decide (Found p)
search @q Sing a
x of
Proved (s :&: q) -> Sigma v (OrP p q a) -> Decision (Found (OrP p q) @@ a)
forall a. a -> Decision a
Proved (Sigma v (OrP p q a) -> Decision (Found (OrP p q) @@ a))
-> Sigma v (OrP p q a) -> Decision (Found (OrP p q) @@ a)
forall a b. (a -> b) -> a -> b
$ Sing fst
s Sing fst -> (OrP p q a @@ fst) -> Sigma v (OrP p q a)
forall s (a :: s ~> *) (fst :: s).
Sing fst -> (a @@ fst) -> Sigma s a
:&: Apply (q a) fst -> Either (Apply (p a) fst) (Apply (q a) fst)
forall a b. b -> Either a b
Right Apply (q a) fst
q
Disproved vq :: Refuted (Found q @@ a)
vq -> Refuted (Sigma v (OrP p q a)) -> Decision (Found (OrP p q) @@ a)
forall a. Refuted a -> Decision a
Disproved (Refuted (Sigma v (OrP p q a)) -> Decision (Found (OrP p q) @@ a))
-> Refuted (Sigma v (OrP p q a)) -> Decision (Found (OrP p q) @@ a)
forall a b. (a -> b) -> a -> b
$ \case
s :: Sing fst
s :&: Left p -> Refuted (Found p @@ a)
vp (Sing fst
s Sing fst -> (p a @@ fst) -> Sigma v (p a)
forall s (a :: s ~> *) (fst :: s).
Sing fst -> (a @@ fst) -> Sigma s a
:&: p a @@ fst
p)
s :: Sing fst
s :&: Right q -> Refuted (Found q @@ a)
vq (Sing fst
s Sing fst -> (q a @@ fst) -> Sigma v (q a)
forall s (a :: s ~> *) (fst :: s).
Sing fst -> (a @@ fst) -> Sigma s a
:&: q a @@ fst
q)
instance (Searchable p, Searchable q) => Decidable (Found (AndP p q)) where
decide :: Sing a -> Decision (Found (AndP p q) @@ a)
decide x :: Sing a
x = case Sing a -> Decision (Found p @@ a)
forall k1 v (p :: ParamPred k1 v). Searchable p => Decide (Found p)
search @p Sing a
x of
Proved (s :&: p) -> case Sing a -> Decision (Found q @@ a)
forall k1 v (p :: ParamPred k1 v). Searchable p => Decide (Found p)
search @q Sing a
x of
Proved (t :&: q) -> Sigma (v, u) (AndP p q a) -> Decision (Found (AndP p q) @@ a)
forall a. a -> Decision a
Proved (Sigma (v, u) (AndP p q a) -> Decision (Found (AndP p q) @@ a))
-> Sigma (v, u) (AndP p q a) -> Decision (Found (AndP p q) @@ a)
forall a b. (a -> b) -> a -> b
$ Sing fst -> Sing fst -> STuple2 '(fst, fst)
forall a0 b0 (n1 :: a0) (n2 :: b0).
Sing n1 -> Sing n2 -> STuple2 '(n1, n2)
STuple2 Sing fst
s Sing fst
t Sing '(fst, fst)
-> (AndP p q a @@ '(fst, fst)) -> Sigma (v, u) (AndP p q a)
forall s (a :: s ~> *) (fst :: s).
Sing fst -> (a @@ fst) -> Sigma s a
:&: (p a @@ fst
p, q a @@ fst
q)
Disproved vq :: Refuted (Found q @@ a)
vq -> Refuted (Sigma (v, u) (AndP p q a))
-> Decision (Found (AndP p q) @@ a)
forall a. Refuted a -> Decision a
Disproved (Refuted (Sigma (v, u) (AndP p q a))
-> Decision (Found (AndP p q) @@ a))
-> Refuted (Sigma (v, u) (AndP p q a))
-> Decision (Found (AndP p q) @@ a)
forall a b. (a -> b) -> a -> b
$ \case
STuple2 _ t :&: (_, q) -> Refuted (Found q @@ a)
vq Refuted (Found q @@ a) -> Refuted (Found q @@ a)
forall a b. (a -> b) -> a -> b
$ Sing n2
t Sing n2 -> (q a @@ n2) -> Sigma u (q a)
forall s (a :: s ~> *) (fst :: s).
Sing fst -> (a @@ fst) -> Sigma s a
:&: q a @@ n2
q
Disproved vp :: Refuted (Found p @@ a)
vp -> Refuted (Sigma (v, u) (AndP p q a))
-> Decision (Found (AndP p q) @@ a)
forall a. Refuted a -> Decision a
Disproved (Refuted (Sigma (v, u) (AndP p q a))
-> Decision (Found (AndP p q) @@ a))
-> Refuted (Sigma (v, u) (AndP p q a))
-> Decision (Found (AndP p q) @@ a)
forall a b. (a -> b) -> a -> b
$ \case
STuple2 s _ :&: (p, _) -> Refuted (Found p @@ a)
vp Refuted (Found p @@ a) -> Refuted (Found p @@ a)
forall a b. (a -> b) -> a -> b
$ Sing n1
s Sing n1 -> (p a @@ n1) -> Sigma v (p a)
forall s (a :: s ~> *) (fst :: s).
Sing fst -> (a @@ fst) -> Sigma s a
:&: p a @@ n1
p
instance (Selectable p, Selectable q) => Provable (Found (AndP p q)) where
prove :: Sing a -> Found (AndP p q) @@ a
prove x :: Sing a
x = case Sing a -> Found p @@ a
forall k1 v (p :: ParamPred k1 v). Selectable p => Prove (Found p)
select @p Sing a
x of
s :&: p -> case Sing a -> Found q @@ a
forall k1 v (p :: ParamPred k1 v). Selectable p => Prove (Found p)
select @q Sing a
x of
t :&: q -> Sing fst -> Sing fst -> STuple2 '(fst, fst)
forall a0 b0 (n1 :: a0) (n2 :: b0).
Sing n1 -> Sing n2 -> STuple2 '(n1, n2)
STuple2 Sing fst
s Sing fst
t Sing '(fst, fst)
-> (AndP p q a @@ '(fst, fst)) -> Sigma (v, u) (AndP p q a)
forall s (a :: s ~> *) (fst :: s).
Sing fst -> (a @@ fst) -> Sigma s a
:&: (p a @@ fst
p, q a @@ fst
q)