packages feed

decidable 0.3.1.0 → 0.3.1.1

raw patch · 9 files changed

+1197/−917 lines, 9 filesdep ~functor-productsdep ~microlensdep ~singletonsPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: functor-products, microlens, singletons, singletons-base, vinyl

API changes (from Hackage documentation)

- Data.Type.Predicate: data Decision a
+ Data.Type.Predicate: data () => Decision a
- Data.Type.Universe: [IS] :: forall {k} (bs :: [k]) (b :: k) (b1 :: k). Index bs b -> Index (b1 : bs) b
+ Data.Type.Universe: [IS] :: forall {k} (bs :: [k]) (b :: k) (b1 :: k). Index bs b -> Index (b1 ': bs) b
- Data.Type.Universe: [IZ] :: forall {k} (b :: k) (as :: [k]). Index (b : as) b
+ Data.Type.Universe: [IZ] :: forall {k} (b :: k) (as :: [k]). Index (b ': as) b
- Data.Type.Universe: [NEHead] :: forall {k} (b :: k) (as :: [k]). NEIndex (b :| as) b
+ Data.Type.Universe: [NEHead] :: forall {k} (b :: k) (as :: [k]). NEIndex (b ':| as) b
- Data.Type.Universe: [NETail] :: forall {k} (as :: [k]) (b :: k) (b1 :: k). Index as b -> NEIndex (b1 :| as) b
+ Data.Type.Universe: [NETail] :: forall {k} (as :: [k]) (b :: k) (b1 :: k). Index as b -> NEIndex (b1 ':| as) b
- Data.Type.Universe: data IIdentity (a :: Identity k) (b :: k)
+ Data.Type.Universe: data () => IIdentity (a :: Identity k) (b :: k)
- Data.Type.Universe: data IJust (a :: Maybe k) (b :: k)
+ Data.Type.Universe: data () => IJust (a :: Maybe k) (b :: k)
- Data.Type.Universe: data IRight (a :: Either j k) (b :: k)
+ Data.Type.Universe: data () => IRight (a :: Either j k) (b :: k)
- Data.Type.Universe: data ISnd (a :: (j, k)) (b :: k)
+ Data.Type.Universe: data () => ISnd (a :: (j, k)) (b :: k)
- Data.Type.Universe: data Index (a :: [k]) (b :: k)
+ Data.Type.Universe: data () => Index (a :: [k]) (b :: k)
- Data.Type.Universe: data NEIndex (a :: NonEmpty k) (b :: k)
+ Data.Type.Universe: data () => NEIndex (a :: NonEmpty k) (b :: k)

Files

CHANGELOG.md view
@@ -1,6 +1,15 @@ Changelog ========= +Version 0.3.1.1+---------------++*February 27, 2024*++<https://github.com/mstksg/functor-products/releases/tag/v0.3.1.1>++*   Remove upper bounds and deprecated pragmas+ Version 0.3.1.0 --------------- 
decidable.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           decidable-version:        0.3.1.0+version:        0.3.1.1 synopsis:       Combinators for manipulating dependently-typed predicates. description:    This library provides combinators and typeclasses for working and manipulating                 type-level predicates in Haskell, which are represented as matchable type-level@@ -47,9 +47,9 @@   ghc-options: -Wall -Wredundant-constraints -Wcompat -Werror=incomplete-patterns   build-depends:       base >=4.16 && <5-    , functor-products >=0.1.2 && <0.2-    , microlens <0.5-    , singletons >=3.0 && <3.1-    , singletons-base <3.2-    , vinyl <0.15+    , functor-products >=0.1.2+    , microlens+    , singletons >=3.0+    , singletons-base+    , vinyl   default-language: Haskell2010
src/Data/Type/Predicate.hs view
@@ -1,17 +1,18 @@ {-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE ConstraintKinds     #-}-{-# LANGUAGE DefaultSignatures   #-}-{-# LANGUAGE EmptyCase           #-}-{-# LANGUAGE FlexibleContexts    #-}-{-# LANGUAGE FlexibleInstances   #-}-{-# LANGUAGE InstanceSigs        #-}-{-# LANGUAGE LambdaCase          #-}-{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE EmptyCase #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications    #-}-{-# LANGUAGE TypeFamilies        #-}-{-# LANGUAGE TypeInType          #-}-{-# LANGUAGE TypeOperators       #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}  -- | -- Module      : Data.Type.Predicate@@ -24,49 +25,72 @@ -- -- Combinators for working with type-level predicates, along with -- typeclasses for canonical proofs and deciding functions.--- module Data.Type.Predicate (-    -- * Predicates-    Predicate, Wit(..)-    -- ** Construct Predicates-  , TyPred, Evident, EqualTo, BoolPred, Impossible, In-    -- ** Manipulate predicates-  , PMap, type Not, decideNot-    -- * Provable Predicates-  , Prove, type (-->), type (-->#)-  , Provable(..)-  , Disprovable, disprove-  , ProvableTC, proveTC-  , TFunctor(..)-  , compImpl-    -- * Decidable Predicates-  , Decide, type (-?>), type (-?>#)-  , Decidable(..)-  , DecidableTC, decideTC-  , DFunctor(..)+  -- * Predicates+  Predicate,+  Wit (..),++  -- ** Construct Predicates+  TyPred,+  Evident,+  EqualTo,+  BoolPred,+  Impossible,+  In,++  -- ** Manipulate predicates+  PMap,+  type Not,+  decideNot,++  -- * Provable Predicates+  Prove,+  type (-->),+  type (-->#),+  Provable (..),+  Disprovable,+  disprove,+  ProvableTC,+  proveTC,+  TFunctor (..),+  compImpl,++  -- * Decidable Predicates+  Decide,+  type (-?>),+  type (-?>#),+  Decidable (..),+  DecidableTC,+  decideTC,+  DFunctor (..),+   -- * Manipulate Decisions-  , Decision(..)-  , flipDecision, mapDecision-  , elimDisproof-  , forgetDisproof, forgetProof, isProved, isDisproved-  , mapRefuted-  ) where+  Decision (..),+  flipDecision,+  mapDecision,+  elimDisproof,+  forgetDisproof,+  forgetProof,+  isProved,+  isDisproved,+  mapRefuted,+) where -import           Data.Either.Singletons-import           Data.Function.Singletons-import           Data.Functor.Identity-import           Data.Functor.Identity.Singletons-import           Data.Kind-import           Data.List.NonEmpty               (NonEmpty(..))-import           Data.List.Singletons hiding      (ElemSym1)-import           Data.Maybe-import           Data.Maybe.Singletons-import           Data.Singletons-import           Data.Singletons.Decide-import           Data.Tuple.Singletons-import           Data.Type.Functor.Product-import           Data.Void-import qualified Data.List.NonEmpty.Singletons    as NE+import Data.Either.Singletons+import Data.Function.Singletons+import Data.Functor.Identity+import Data.Functor.Identity.Singletons+import Data.Kind+import Data.List.NonEmpty (NonEmpty (..))+import qualified Data.List.NonEmpty.Singletons as NE+import Data.List.Singletons hiding (ElemSym1)+import Data.Maybe+import Data.Maybe.Singletons+import Data.Singletons+import Data.Singletons.Decide+import Data.Tuple.Singletons+import Data.Type.Functor.Product+import Data.Void  -- | A type-level predicate in Haskell.  We say that the predicate @P :: -- 'Predicate' k@ is true/satisfied by input @x :: k@ if there exists@@ -139,6 +163,7 @@ -- 'Evident' :: 'Predicate' k -- @ data Evident :: Predicate k+ type instance Apply Evident a = Sing a  -- | The always-false predicate@@ -177,7 +202,7 @@ -- -- It essentially turns a @k ~> 'Type'@ ("matchable" @'Predicate' k@) /back -- into/ a @k -> 'Type'@ predicate.-newtype Wit p a = Wit { getWit :: p @@ a }+newtype Wit p a = Wit {getWit :: p @@ a}  -- | A decision function for predicate @p@.  See 'Decidable' for more -- information.@@ -224,22 +249,21 @@ --     transformers (predicates parameterized on other predicates) easily, --     by refering to 'Decidable' instances of the transformed predicates. class Decidable p where-    -- | The canonical decision function for predicate @p@.-    ---    -- Note that 'decide' is ambiguously typed, so you /always/ need to call by-    -- specifying the predicate you want to prove using TypeApplications-    -- syntax:-    ---    -- @-    -- 'decide' \@MyPredicate-    -- @-    ---    -- See 'decideTC' and 'DecidableTC' for a version that isn't ambiguously-    -- typed, but only works when @p@ is a type constructor.-    decide :: Decide p--    default decide :: Provable p => Decide p-    decide = Proved . prove @p+  -- | The canonical decision function for predicate @p@.+  --+  -- Note that 'decide' is ambiguously typed, so you /always/ need to call by+  -- specifying the predicate you want to prove using TypeApplications+  -- syntax:+  --+  -- @+  -- 'decide' \@MyPredicate+  -- @+  --+  -- See 'decideTC' and 'DecidableTC' for a version that isn't ambiguously+  -- typed, but only works when @p@ is a type constructor.+  decide :: Decide p+  default decide :: Provable p => Decide p+  decide = Proved . prove @p  -- | A typeclass for provable predicates (constructivist tautologies).  In -- some context, these are also known as "views".@@ -263,20 +287,20 @@ --     transformers (predicates parameterized on other predicates) easily, --     by refering to 'Provable' instances of the transformed predicates. class Provable p where-    -- | The canonical proving function for predicate @p@ (or a canonical-    -- view function for view @p@).-    ---    -- Note that 'prove' is ambiguously typed, so you /always/ need to call-    -- by specifying the predicate you want to prove using TypeApplications-    -- syntax:-    ---    -- @-    -- 'prove' \@MyPredicate-    -- @-    ---    -- See 'proveTC' and 'ProvableTC' for a version that isn't ambiguously-    -- typed, but only works when @p@ is a type constructor.-    prove :: Prove p+  -- | The canonical proving function for predicate @p@ (or a canonical+  -- view function for view @p@).+  --+  -- Note that 'prove' is ambiguously typed, so you /always/ need to call+  -- by specifying the predicate you want to prove using TypeApplications+  -- syntax:+  --+  -- @+  -- 'prove' \@MyPredicate+  -- @+  --+  -- See 'proveTC' and 'ProvableTC' for a version that isn't ambiguously+  -- typed, but only works when @p@ is a type constructor.+  prove :: Prove p  -- | @'Disprovable' p@ is a constraint that @p@ can be disproven. type Disprovable p = Provable (Not p)@@ -337,7 +361,7 @@ -- that are GADT type constructors. -- -- @since 0.1.1.0-type ProvableTC  p = Provable  (TyPred p)+type ProvableTC p = Provable (TyPred p)  -- | The canonical proving function for @'DecidableTC' t@. --@@ -352,162 +376,181 @@ -- | Implicatons @p '-?>' q@ can be lifted "through" a 'DFunctor' into an -- @f p '-?>' f q@. class DFunctor f where-    dmap :: forall p q. (p -?> q) -> (f p -?> f q)+  dmap :: forall p q. (p -?> q) -> (f p -?> f q)  -- | Implicatons @p '-->' q@ can be lifted "through" a 'TFunctor' into an -- @f p '-->' f q@. class TFunctor f where-    tmap :: forall p q. (p --> q) -> (f p --> f q)+  tmap :: forall p q. (p --> q) -> (f p --> f q)  instance (SDecide k, SingI (a :: k)) => Decidable (EqualTo a) where-    decide = (sing %~)+  decide = (sing %~)  instance Decidable Evident instance Provable Evident where-    prove = id+  prove = id  -- | @since 3.0.0 instance Decidable (TyPred WrappedSing)+ -- | @since 3.0.0 instance Provable (TyPred WrappedSing) where-    prove = WrapSing-+  prove = WrapSing  -- | @since 3.0.0 instance Provable p => Provable (TyPred (Rec (Wit p))) where-    prove = mapProd (Wit . prove @p) . singProd+  prove = mapProd (Wit . prove @p) . singProd+ -- | @since 3.0.0 instance Decidable p => Decidable (TyPred (Rec (Wit p))) where-    decide = \case-      SNil         -> Proved RNil-      x `SCons` xs -> case decide @p x of-        Proved p -> case decideTC xs of-          Proved ps -> Proved $ Wit p :& ps-          Disproved vs -> Disproved $ \case-            _ :& ps -> vs ps-        Disproved v -> Disproved $ \case-          Wit p :& _ -> v p+  decide = \case+    SNil -> Proved RNil+    x `SCons` xs -> case decide @p x of+      Proved p -> case decideTC xs of+        Proved ps -> Proved $ Wit p :& ps+        Disproved vs -> Disproved $ \case+          _ :& ps -> vs ps+      Disproved v -> Disproved $ \case+        Wit p :& _ -> v p  -- | @since 3.0.0 instance Provable (TyPred (Rec WrappedSing)) where-    prove = mapProd WrapSing . singProd+  prove = mapProd WrapSing . singProd+ -- | @since 3.0.0 instance Decidable (TyPred (Rec WrappedSing))  -- | @since 3.0.0 instance Provable p => Provable (TyPred (PMaybe (Wit p))) where-    prove = mapProd (Wit . prove @p) . singProd+  prove = mapProd (Wit . prove @p) . singProd+ -- | @since 3.0.0 instance Decidable p => Decidable (TyPred (PMaybe (Wit p))) where-    decide = \case-      SNothing -> Proved PNothing-      SJust x  -> mapDecision (PJust . Wit) (\case PJust (Wit p) -> p)-                . decide @p-                $ x+  decide = \case+    SNothing -> Proved PNothing+    SJust x ->+      mapDecision (PJust . Wit) (\case PJust (Wit p) -> p)+        . decide @p+        $ x  -- | @since 3.0.0 instance Provable (TyPred (PMaybe WrappedSing)) where-    prove = mapProd WrapSing . singProd+  prove = mapProd WrapSing . singProd+ -- | @since 3.0.0 instance Decidable (TyPred (PMaybe WrappedSing))  -- | @since 3.0.0 instance Provable p => Provable (TyPred (NERec (Wit p))) where-    prove = mapProd (Wit . prove @p) . singProd+  prove = mapProd (Wit . prove @p) . singProd+ -- | @since 3.0.0 instance Decidable p => Decidable (TyPred (NERec (Wit p))) where-    decide = \case-      x NE.:%| xs -> case decide @p x of-        Proved p -> case decideTC xs of-          Proved ps -> Proved $ Wit p :&| ps-          Disproved vs -> Disproved $ \case-            _ :&| ps -> vs ps-        Disproved v -> Disproved $ \case-          Wit p :&| _ -> v p+  decide = \case+    x NE.:%| xs -> case decide @p x of+      Proved p -> case decideTC xs of+        Proved ps -> Proved $ Wit p :&| ps+        Disproved vs -> Disproved $ \case+          _ :&| ps -> vs ps+      Disproved v -> Disproved $ \case+        Wit p :&| _ -> v p  -- | @since 3.0.0 instance Provable (TyPred (NERec WrappedSing)) where-    prove = mapProd WrapSing . singProd+  prove = mapProd WrapSing . singProd+ -- | @since 3.0.0 instance Decidable (TyPred (NERec WrappedSing))  -- | @since 3.0.0 instance Provable p => Provable (TyPred (PIdentity (Wit p))) where-    prove = mapProd (Wit . prove @p) . singProd+  prove = mapProd (Wit . prove @p) . singProd+ -- | @since 3.0.0 instance Decidable p => Decidable (TyPred (PIdentity (Wit p))) where-    decide = \case-      SIdentity x -> mapDecision (PIdentity . Wit) (\case PIdentity (Wit p) -> p)-                   . decide @p-                   $ x+  decide = \case+    SIdentity x ->+      mapDecision (PIdentity . Wit) (\case PIdentity (Wit p) -> p)+        . decide @p+        $ x  -- | @since 3.0.0 instance Provable (TyPred (PIdentity WrappedSing)) where-    prove = mapProd WrapSing . singProd+  prove = mapProd WrapSing . singProd+ -- | @since 3.0.0 instance Decidable (TyPred (PIdentity WrappedSing))  -- | @since 3.0.0 instance Provable p => Provable (TyPred (PEither (Wit p))) where-    prove = mapProd (Wit . prove @p) . singProd+  prove = mapProd (Wit . prove @p) . singProd+ -- | @since 3.0.0 instance Decidable p => Decidable (TyPred (PEither (Wit p))) where-    decide = \case-      SLeft  x -> Proved $ PLeft x-      SRight y -> mapDecision (PRight . Wit) (\case PRight (Wit p) -> p)-                . decide @p-                $ y+  decide = \case+    SLeft x -> Proved $ PLeft x+    SRight y ->+      mapDecision (PRight . Wit) (\case PRight (Wit p) -> p)+        . decide @p+        $ y  -- | @since 3.0.0 instance Provable (TyPred (PEither WrappedSing)) where-    prove = mapProd WrapSing . singProd+  prove = mapProd WrapSing . singProd+ -- | @since 3.0.0 instance Decidable (TyPred (PEither WrappedSing))  -- | @since 3.0.0 instance Provable p => Provable (TyPred (PTup (Wit p))) where-    prove = mapProd (Wit . prove @p) . singProd+  prove = mapProd (Wit . prove @p) . singProd+ -- | @since 3.0.0 instance Decidable p => Decidable (TyPred (PTup (Wit p))) where-    decide (STuple2 x y) = mapDecision (PTup x . Wit) (\case PTup _ (Wit p) -> p)-                         . decide @p-                         $ y+  decide (STuple2 x y) =+    mapDecision (PTup x . Wit) (\case PTup _ (Wit p) -> p)+      . decide @p+      $ y  -- | @since 3.0.0 instance Provable (TyPred (PTup WrappedSing)) where-    prove = mapProd WrapSing . singProd+  prove = mapProd WrapSing . singProd+ -- | @since 3.0.0 instance Decidable (TyPred (PTup WrappedSing))  instance (Decidable p, SingI f) => Decidable (PMap f p) where-    decide = decide @p . applySing (sing :: Sing f)+  decide = decide @p . applySing (sing :: Sing f)  instance (Provable p, SingI f) => Provable (PMap f p) where-    prove = prove @p . applySing (sing :: Sing f)+  prove = prove @p . applySing (sing :: Sing f)  -- | Compose two implications.-compImpl-    :: forall p q r. ()-    => p --> q-    -> q --> r-    -> p --> r+compImpl ::+  forall p q r.+  () =>+  p --> q ->+  q --> r ->+  p --> r compImpl f g s = g s . f s  -- | @'Not' p@ is the predicate that @p@ is not true. data Not :: Predicate k -> Predicate k+ type instance Apply (Not p) a = Refuted (p @@ a)  instance Decidable p => Decidable (Not p) where-    decide (x :: Sing a) = decideNot @p @a (decide @p x)+  decide (x :: Sing a) = decideNot @p @a (decide @p x)  instance Provable (Not Impossible) where-    prove x v = absurd $ v x+  prove x v = absurd $ v x  -- | Decide @'Not' p@ based on decisions of @p@.-decideNot-    :: forall p a. ()-    => Decision (p @@ a)-    -> Decision (Not p @@ a)+decideNot ::+  forall p a.+  () =>+  Decision (p @@ a) ->+  Decision (Not p @@ a) decideNot = flipDecision  -- | Flip the contents of a decision.  Turn a proof of @a@ into a disproof@@ -517,42 +560,42 @@ -- 'Data.Type.Predicate.Logic.doubleNegation' for a situation where it is. -- -- @since 0.1.1.0-flipDecision-    :: Decision a-    -> Decision (Refuted a)+flipDecision ::+  Decision a ->+  Decision (Refuted a) flipDecision = \case-    Proved    p -> Disproved ($ p)-    Disproved v -> Proved v+  Proved p -> Disproved ($ p)+  Disproved v -> Proved v  -- | Map over the value inside a 'Decision'.-mapDecision-    :: (a -> b)-    -> (b -> a)-    -> Decision a-    -> Decision b+mapDecision ::+  (a -> b) ->+  (b -> a) ->+  Decision a ->+  Decision b mapDecision f g = \case-    Proved    p -> Proved    $ f p-    Disproved v -> Disproved $ mapRefuted g v+  Proved p -> Proved $ f p+  Disproved v -> Disproved $ mapRefuted g v  -- | Converts a 'Decision' to a 'Maybe'.  Drop the witness of disproof of -- @a@, returning 'Just' if 'Proved' (with the proof) and 'Nothing' if -- 'Disproved'. -- -- @since 0.1.1.0-forgetDisproof-    :: Decision a-    -> Maybe a+forgetDisproof ::+  Decision a ->+  Maybe a forgetDisproof = \case-    Proved    p -> Just p-    Disproved _ -> Nothing+  Proved p -> Just p+  Disproved _ -> Nothing  -- | Drop the witness of proof of @a@, returning 'Nothing' if 'Proved' and -- 'Just' if 'Disproved' (with the disproof). -- -- @since 0.1.1.0-forgetProof-    :: Decision a-    -> Maybe (Refuted a)+forgetProof ::+  Decision a ->+  Maybe (Refuted a) forgetProof = forgetDisproof . flipDecision  -- | Boolean test if a 'Decision' is 'Proved'.@@ -571,22 +614,22 @@ -- branch of 'Decision' to certaintify the proof. -- -- @since 0.1.2.0-elimDisproof-    :: Decision a-    -> Refuted (Refuted a)-    -> a+elimDisproof ::+  Decision a ->+  Refuted (Refuted a) ->+  a elimDisproof = \case-    Proved    p -> const p-    Disproved v -> absurd . ($ v)+  Proved p -> const p+  Disproved v -> absurd . ($ v)  -- | Change the target of a 'Refuted' with a contravariant mapping -- function. -- -- @since 0.1.2.0-mapRefuted-    :: (a -> b)-    -> Refuted b-    -> Refuted a+mapRefuted ::+  (a -> b) ->+  Refuted b ->+  Refuted a mapRefuted = flip (.)  -- | @'In' f as@ is a predicate that a given input @a@ is a member of@@ -594,52 +637,52 @@ type In (f :: Type -> Type) (as :: f k) = ElemSym1 f as  instance (SDecide k, SingI (as :: [k])) => Decidable (In [] as) where-    decide :: forall a. Sing a -> Decision (Index as a)-    decide x = go (sing @as)-      where-        go :: Sing bs -> Decision (Index bs a)-        go = \case-          SNil         -> Disproved $ \case {}-          y `SCons` ys -> case x %~ y of-            Proved Refl -> Proved IZ-            Disproved v -> case go ys of-              Proved i    -> Proved (IS i)-              Disproved u -> Disproved $ \case-                IZ   -> v Refl-                IS i -> u i+  decide :: forall a. Sing a -> Decision (Index as a)+  decide x = go (sing @as)+    where+      go :: Sing bs -> Decision (Index bs a)+      go = \case+        SNil -> Disproved $ \case {}+        y `SCons` ys -> case x %~ y of+          Proved Refl -> Proved IZ+          Disproved v -> case go ys of+            Proved i -> Proved (IS i)+            Disproved u -> Disproved $ \case+              IZ -> v Refl+              IS i -> u i  instance (SDecide k, SingI (as :: Maybe k)) => Decidable (In Maybe as) where-    decide x = case sing @as of-      SNothing -> Disproved $ \case {}-      SJust y  -> case x %~ y of-        Proved Refl -> Proved IJust-        Disproved v -> Disproved $ \case IJust -> v Refl+  decide x = case sing @as of+    SNothing -> Disproved $ \case {}+    SJust y -> case x %~ y of+      Proved Refl -> Proved IJust+      Disproved v -> Disproved $ \case IJust -> v Refl  instance (SDecide k, SingI (as :: Either j k)) => Decidable (In (Either j) as) where-    decide x = case sing @as of-      SLeft _  -> Disproved $ \case {}-      SRight y -> case x %~ y of-        Proved Refl -> Proved IRight-        Disproved v -> Disproved $ \case IRight -> v Refl+  decide x = case sing @as of+    SLeft _ -> Disproved $ \case {}+    SRight y -> case x %~ y of+      Proved Refl -> Proved IRight+      Disproved v -> Disproved $ \case IRight -> v Refl  instance (SDecide k, SingI (as :: NonEmpty k)) => Decidable (In NonEmpty as) where-    decide x = case sing @as of-      y NE.:%| (Sing :: Sing bs) -> case x %~ y of-        Proved Refl -> Proved NEHead-        Disproved v -> case decide @(In [] bs) x of-          Proved i    -> Proved $ NETail i-          Disproved u -> Disproved $ \case-            NEHead   -> v Refl-            NETail i -> u i+  decide x = case sing @as of+    y NE.:%| (Sing :: Sing bs) -> case x %~ y of+      Proved Refl -> Proved NEHead+      Disproved v -> case decide @(In [] bs) x of+        Proved i -> Proved $ NETail i+        Disproved u -> Disproved $ \case+          NEHead -> v Refl+          NETail i -> u i  instance (SDecide k, SingI (as :: (j, k))) => Decidable (In ((,) j) as) where-    decide x = case sing @as of-      STuple2 _ y -> case x %~ y of-        Proved Refl -> Proved ISnd-        Disproved v -> Disproved $ \case ISnd -> v Refl+  decide x = case sing @as of+    STuple2 _ y -> case x %~ y of+      Proved Refl -> Proved ISnd+      Disproved v -> Disproved $ \case ISnd -> v Refl  instance (SDecide k, SingI (as :: Identity k)) => Decidable (In Identity as) where-    decide x = case sing @as of-      SIdentity y -> case x %~ y of-        Proved Refl -> Proved IId-        Disproved v -> Disproved $ \case IId -> v Refl+  decide x = case sing @as of+    SIdentity y -> case x %~ y of+      Proved Refl -> Proved IId+      Disproved v -> Disproved $ \case IId -> v Refl
src/Data/Type/Predicate/Auto.hs view
@@ -1,17 +1,17 @@-{-# LANGUAGE AllowAmbiguousTypes   #-}-{-# LANGUAGE ConstraintKinds       #-}-{-# LANGUAGE EmptyCase             #-}-{-# LANGUAGE FlexibleContexts      #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE KindSignatures        #-}-{-# LANGUAGE LambdaCase            #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE EmptyCase #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE ScopedTypeVariables   #-}-{-# LANGUAGE TypeApplications      #-}-{-# LANGUAGE TypeFamilies          #-}-{-# LANGUAGE TypeInType            #-}-{-# LANGUAGE TypeOperators         #-}-{-# LANGUAGE UndecidableInstances  #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}  -- | -- Module      : Data.Type.Predicate.Auto@@ -28,28 +28,30 @@ -- @since 0.1.1.0 module Data.Type.Predicate.Auto (   -- * Automatically generate witnesses at compile-time-    Auto(..)-  , autoTC-  , AutoNot-  , autoNot-  , autoAny, autoNotAll-  , AutoProvable+  Auto (..),+  autoTC,+  AutoNot,+  autoNot,+  autoAny,+  autoNotAll,+  AutoProvable,+   -- ** Helper classes-  , AutoElem(..)-  , AutoAll(..)-  ) where+  AutoElem (..),+  AutoAll (..),+) where -import           Data.Functor.Identity-import           Data.List.NonEmpty                 (NonEmpty(..))-import           Data.Singletons-import           Data.Singletons.Sigma-import           Data.Type.Equality-import           Data.Type.Functor.Product-import           Data.Type.Predicate-import           Data.Type.Predicate.Logic-import           Data.Type.Predicate.Param-import           Data.Type.Predicate.Quantification-import           Data.Type.Universe+import Data.Functor.Identity+import Data.List.NonEmpty (NonEmpty (..))+import Data.Singletons+import Data.Singletons.Sigma+import Data.Type.Equality+import Data.Type.Functor.Product+import Data.Type.Predicate+import Data.Type.Predicate.Logic+import Data.Type.Predicate.Param+import Data.Type.Predicate.Quantification+import Data.Type.Universe  -- | Automatically generate a witness for predicate @p@ applied to input -- @a@.@@ -76,14 +78,14 @@ -- For these, the compiler needs help; you can use 'autoAny' and -- 'autoNotAll' for these situations. class Auto (p :: Predicate k) (a :: k) where-    -- | Have the compiler generate a witness for @p \@\@ a@.-    ---    -- Must be called using type application syntax:-    ---    -- @-    -- 'auto' @_ @p @a-    -- @-    auto :: p @@ a+  -- | Have the compiler generate a witness for @p \@\@ a@.+  --+  -- Must be called using type application syntax:+  --+  -- @+  -- 'auto' @_ @p @a+  -- @+  auto :: p @@ a  -- | A version of 'auto' that "just works" with type inference, if the -- predicate is a type constructor.@@ -93,20 +95,20 @@ autoTC = auto @_ @(TyPred t) @a  instance SingI a => Auto Evident a where-    auto = sing+  auto = sing  -- | @since 0.1.2.0 instance SingI a => Auto (Not Impossible) a where-    auto = ($ sing)+  auto = ($ sing)  instance Auto (EqualTo a) a where-    auto = Refl+  auto = Refl  instance (Auto p a, Auto q a) => Auto (p &&& q) a where-    auto = (auto @_ @p @a, auto @_ @q @a)+  auto = (auto @_ @p @a, auto @_ @q @a)  instance Auto q a => Auto (p ==> q) a where-    auto _ = auto @_ @q @a+  auto _ = auto @_ @q @a  -- | Helper "predicate transformer" that gives you an instant 'auto' for -- any 'Provable' instance.@@ -123,10 +125,11 @@ -- -- 'AutoProvable' is essentially the identity function. data AutoProvable :: Predicate k -> Predicate k+ type instance Apply (AutoProvable p) a = p @@ a  instance (Provable p, SingI a) => Auto (AutoProvable p) a where-    auto = prove @p @a sing+  auto = prove @p @a sing  -- | Typeclass representing 'Elem's pointing to an @a :: k@ that can be -- generated automatically from type-level collection @as :: f k@.@@ -150,37 +153,37 @@ -- -- IS (IS IZ) -- @ class AutoElem f (as :: f k) (a :: k) where-    -- | Generate the 'Elem' pointing to the @a :: @ in a type-level-    -- collection @as :: f k@.-    autoElem :: Elem f as a+  -- | Generate the 'Elem' pointing to the @a :: @ in a type-level+  -- collection @as :: f k@.+  autoElem :: Elem f as a  instance {-# OVERLAPPING #-} AutoElem [] (a ': as) a where-    autoElem = IZ+  autoElem = IZ  instance {-# OVERLAPPING #-} AutoElem [] as a => AutoElem [] (b ': as) a where-    autoElem = IS autoElem+  autoElem = IS autoElem  instance AutoElem Maybe ('Just a) a where-    autoElem = IJust+  autoElem = IJust  instance AutoElem (Either j) ('Right a) a where-    autoElem = IRight+  autoElem = IRight  instance AutoElem NonEmpty (a ':| as) a where-    autoElem = NEHead+  autoElem = NEHead  instance AutoElem [] as a => AutoElem NonEmpty (b ':| as) a where-    autoElem = NETail autoElem+  autoElem = NETail autoElem  -- | @since 0.1.2.0 instance AutoElem ((,) j) '(w, a) a where-    autoElem = ISnd+  autoElem = ISnd  instance AutoElem Identity ('Identity a) a where-    autoElem = IId+  autoElem = IId  instance AutoElem f as a => Auto (In f as) a where-    auto = autoElem @_ @f @as @a+  auto = autoElem @_ @f @as @a  -- | Helper class for deriving 'Auto' instances for 'All' predicates; each -- 'Universe' instance is expected to implement these if possible, to get@@ -191,66 +194,66 @@ -- -- @since 0.1.2.0 class AutoAll f (p :: Predicate k) (as :: f k) where-    -- | Generate an 'All' for a given predicate over all items in @as@.-    autoAll :: All f p @@ as+  -- | Generate an 'All' for a given predicate over all items in @as@.+  autoAll :: All f p @@ as  instance AutoAll [] p '[] where-    autoAll = WitAll $ \case {}+  autoAll = WitAll $ \case {}  instance (Auto p a, AutoAll [] p as) => AutoAll [] p (a ': as) where-    autoAll = WitAll $ \case-        IZ   -> auto @_ @p @a-        IS i -> runWitAll (autoAll @_ @[] @p @as) i+  autoAll = WitAll $ \case+    IZ -> auto @_ @p @a+    IS i -> runWitAll (autoAll @_ @[] @p @as) i  instance AutoAll Maybe p 'Nothing where-    autoAll = WitAll $ \case {}+  autoAll = WitAll $ \case {}  instance Auto p a => AutoAll Maybe p ('Just a) where-    autoAll = WitAll $ \case IJust -> auto @_ @p @a+  autoAll = WitAll $ \case IJust -> auto @_ @p @a  instance AutoAll (Either j) p ('Left e) where-    autoAll = WitAll $ \case {}+  autoAll = WitAll $ \case {}  instance Auto p a => AutoAll (Either j) p ('Right a) where-    autoAll = WitAll $ \case IRight -> auto @_ @p @a+  autoAll = WitAll $ \case IRight -> auto @_ @p @a  instance (Auto p a, AutoAll [] p as) => AutoAll NonEmpty p (a ':| as) where-    autoAll = WitAll $ \case-        NEHead   -> auto @_ @p @a-        NETail i -> runWitAll (autoAll @_ @[] @p @as) i+  autoAll = WitAll $ \case+    NEHead -> auto @_ @p @a+    NETail i -> runWitAll (autoAll @_ @[] @p @as) i  instance Auto p a => AutoAll ((,) j) p '(w, a) where-    autoAll = WitAll $ \case ISnd -> auto @_ @p @a+  autoAll = WitAll $ \case ISnd -> auto @_ @p @a  instance Auto p a => AutoAll Identity p ('Identity a) where-    autoAll = WitAll $ \case IId -> auto @_ @p @a+  autoAll = WitAll $ \case IId -> auto @_ @p @a  -- | @since 0.1.2.0 instance AutoAll f p as => Auto (All f p) as where-    auto = autoAll @_ @f @p @as+  auto = autoAll @_ @f @p @as  -- | @since 0.1.2.0 instance SingI a => Auto (NotNull []) (a ': as) where-    auto = WitAny IZ sing+  auto = WitAny IZ sing  -- | @since 0.1.2.0 instance SingI a => Auto IsJust ('Just a) where-    auto = WitAny IJust sing+  auto = WitAny IJust sing  -- | @since 0.1.2.0 instance SingI a => Auto IsRight ('Right a) where-    auto = WitAny IRight sing+  auto = WitAny IRight sing  -- | @since 0.1.2.0 instance SingI a => Auto (NotNull NonEmpty) (a ':| as) where-    auto = WitAny NEHead sing+  auto = WitAny NEHead sing  -- | @since 0.1.2.0 instance SingI a => Auto (NotNull ((,) j)) '(w, a) where-    auto = WitAny ISnd sing+  auto = WitAny ISnd sing  instance SingI a => Auto (NotNull Identity) ('Identity a) where-    auto = WitAny IId sing+  auto = WitAny IId sing  -- | An @'AutoNot' p a@ constraint means that @p \@\@ a@ can be proven to -- not be true at compiletime.@@ -270,21 +273,22 @@  -- | @since 0.1.2.0 instance Auto (Found p) (f @@ a) => Auto (Found (PPMap f p)) a where-    auto = case auto @_ @(Found p) @(f @@ a) of-        i :&: p -> i :&: p+  auto = case auto @_ @(Found p) @(f @@ a) of+    i :&: p -> i :&: p  -- | @since 0.1.2.0 instance Auto (NotFound p) (f @@ a) => Auto (NotFound (PPMap f p)) a where-    auto = mapRefuted (\(i :&: p) -> i :&: p)-         $ autoNot @_ @(Found p) @(f @@ a)+  auto =+    mapRefuted (\(i :&: p) -> i :&: p) $+      autoNot @_ @(Found p) @(f @@ a)  -- | @since 0.1.2.0 instance Auto p (f @@ a) => Auto (PMap f p) a where-    auto = auto @_ @p @(f @@ a)+  auto = auto @_ @p @(f @@ a)  -- | @since 0.1.2.0 instance AutoNot p (f @@ a) => Auto (Not (PMap f p)) a where-    auto = autoNot @_ @p @(f @@ a)+  auto = autoNot @_ @p @(f @@ a)  -- | Helper function to generate an @'Any' f p@ if you can pick out -- a specific @a@ in @as@ where the predicate is provable at compile-time.@@ -293,15 +297,16 @@ -- a Haskell typeclass. -- -- @since 0.1.2.0-autoAny-    :: forall f p as a. Auto p a-    => Elem f as a-    -> Any f p @@ as+autoAny ::+  forall f p as a.+  Auto p a =>+  Elem f as a ->+  Any f p @@ as autoAny i = WitAny i (auto @_ @p @a)  -- | @since 0.1.2.0 instance (SingI as, AutoAll f (Not p) as) => Auto (Not (Any f p)) as where-    auto = allNotNone sing $ autoAll @_ @f @(Not p) @as+  auto = allNotNone sing $ autoAll @_ @f @(Not p) @as  -- | Helper function to generate a @'Not' ('All' f p)@ if you can pick out -- a specific @a@ in @as@ where the predicate is disprovable at compile-time.@@ -310,51 +315,63 @@ -- a Haskell typeclass. -- -- @since 0.1.2.0-autoNotAll-    :: forall p f as a. (AutoNot p a, SingI as)-    => Elem f as a-    -> Not (All f p) @@ as+autoNotAll ::+  forall p f as a.+  (AutoNot p a, SingI as) =>+  Elem f as a ->+  Not (All f p) @@ as autoNotAll = anyNotNotAll sing . autoAny  -- | @since 0.1.2.0 instance (SingI as, AutoAll f (Not (Found p)) as) => Auto (Not (Found (AnyMatch f p))) as where-    auto = mapRefuted (\(s :&: WitAny i p) -> WitAny i (s :&: p))-         $ auto @_ @(Not (Any f (Found p))) @as+  auto =+    mapRefuted (\(s :&: WitAny i p) -> WitAny i (s :&: p)) $+      auto @_ @(Not (Any f (Found p))) @as  -- | @since 3.0.0 instance SingI as => Auto (TyPred (Rec WrappedSing)) as where-    auto = proveTC sing+  auto = proveTC sing+ -- | @since 3.0.0 instance SingI as => Auto (TyPred (PMaybe WrappedSing)) as where-    auto = proveTC sing+  auto = proveTC sing+ -- | @since 3.0.0 instance SingI as => Auto (TyPred (NERec WrappedSing)) as where-    auto = proveTC sing+  auto = proveTC sing+ -- | @since 3.0.0 instance SingI as => Auto (TyPred (PEither WrappedSing)) as where-    auto = proveTC sing+  auto = proveTC sing+ -- | @since 3.0.0 instance SingI as => Auto (TyPred (PTup WrappedSing)) as where-    auto = proveTC sing+  auto = proveTC sing+ -- | @since 3.0.0 instance SingI as => Auto (TyPred (PIdentity WrappedSing)) as where-    auto = proveTC sing+  auto = proveTC sing  -- | @since 3.0.0 instance (SingI as, Provable p) => Auto (TyPred (Rec (Wit p))) as where-    auto = proveTC sing+  auto = proveTC sing+ -- | @since 3.0.0 instance (SingI as, Provable p) => Auto (TyPred (PMaybe (Wit p))) as where-    auto = proveTC sing+  auto = proveTC sing+ -- | @since 3.0.0 instance (SingI as, Provable p) => Auto (TyPred (NERec (Wit p))) as where-    auto = proveTC sing+  auto = proveTC sing+ -- | @since 3.0.0 instance (SingI as, Provable p) => Auto (TyPred (PEither (Wit p))) as where-    auto = proveTC sing+  auto = proveTC sing+ -- | @since 3.0.0 instance (SingI as, Provable p) => Auto (TyPred (PTup (Wit p))) as where-    auto = proveTC sing+  auto = proveTC sing+ -- | @since 3.0.0 instance (SingI as, Provable p) => Auto (TyPred (PIdentity (Wit p))) as where-    auto = proveTC sing+  auto = proveTC sing
src/Data/Type/Predicate/Logic.hs view
@@ -1,15 +1,16 @@ {-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE ConstraintKinds     #-}-{-# LANGUAGE FlexibleContexts    #-}-{-# LANGUAGE FlexibleInstances   #-}-{-# LANGUAGE LambdaCase          #-}-{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TupleSections       #-}-{-# LANGUAGE TypeApplications    #-}-{-# LANGUAGE TypeFamilies        #-}-{-# LANGUAGE TypeInType          #-}-{-# LANGUAGE TypeOperators       #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}  -- | -- Module      : Data.Type.Predicate.Logic@@ -24,68 +25,94 @@ -- logical combinators. module Data.Type.Predicate.Logic (   -- * Top and bottom-    Evident, Impossible+  Evident,+  Impossible,+   -- * Logical connectives-  , type Not, decideNot-  , type (&&&), decideAnd-  , type (|||), decideOr, type (^||), type (||^)-  , type (^^^), decideXor-  , type (==>), proveImplies, Implies-  , type (<==>), Equiv+  type Not,+  decideNot,+  type (&&&),+  decideAnd,+  type (|||),+  decideOr,+  type (^||),+  type (||^),+  type (^^^),+  decideXor,+  type (==>),+  proveImplies,+  Implies,+  type (<==>),+  Equiv,+   -- * Logical deductions-  , compImpl, explosion, atom-  , complementation, doubleNegation, tripleNegation, negateTwice-  , contrapositive, contrapositive'+  compImpl,+  explosion,+  atom,+  complementation,+  doubleNegation,+  tripleNegation,+  negateTwice,+  contrapositive,+  contrapositive',+   -- ** Lattice-  , projAndFst, projAndSnd, injOrLeft, injOrRight-  ) where+  projAndFst,+  projAndSnd,+  injOrLeft,+  injOrRight,+) where -import           Data.Singletons-import           Data.Singletons.Decide-import           Data.Type.Predicate-import           Data.Void+import Data.Singletons+import Data.Singletons.Decide+import Data.Type.Predicate+import Data.Void  -- | @p '&&&' q@ is a predicate that both @p@ and @q@ are true. data (&&&) :: Predicate k -> Predicate k -> Predicate k+ type instance Apply (p &&& q) a = (p @@ a, q @@ a) infixr 3 &&&  instance (Decidable p, Decidable q) => Decidable (p &&& q) where-    decide (x :: Sing a) = decideAnd @p @q @a (decide @p x) (decide @q x)+  decide (x :: Sing a) = decideAnd @p @q @a (decide @p x) (decide @q x)  instance (Provable p, Provable q) => Provable (p &&& q) where-    prove x = (prove @p x, prove @q x)+  prove x = (prove @p x, prove @q x)  -- | Decide @p '&&&' q@ based on decisions of @p@ and @q@.-decideAnd-    :: forall p q a. ()-    => Decision (p @@ a)-    -> Decision (q @@ a)-    -> Decision ((p &&& q) @@ a)+decideAnd ::+  forall p q a.+  () =>+  Decision (p @@ a) ->+  Decision (q @@ a) ->+  Decision ((p &&& q) @@ a) decideAnd = \case-    Proved p    -> mapDecision (p,) snd-    Disproved v -> \_ -> Disproved $ \(p, _) -> v p+  Proved p -> mapDecision (p,) snd+  Disproved v -> \_ -> Disproved $ \(p, _) -> v p  -- | @p '|||' q@ is a predicate that either @p@ and @q@ are true. data (|||) :: Predicate k -> Predicate k -> Predicate k+ type instance Apply (p ||| q) a = Either (p @@ a) (q @@ a) infixr 2 |||  -- | Prefers @p@ over @q@. instance (Decidable p, Decidable q) => Decidable (p ||| q) where-    decide (x :: Sing a) = decideOr @p @q @a (decide @p x) (decide @q x)+  decide (x :: Sing a) = decideOr @p @q @a (decide @p x) (decide @q x)  -- | Decide @p '|||' q@ based on decisions of @p@ and @q@. -- -- Prefers @p@ over @q@.-decideOr-    :: forall p q a. ()-    => Decision (p @@ a)-    -> Decision (q @@ a)-    -> Decision ((p ||| q) @@ a)+decideOr ::+  forall p q a.+  () =>+  Decision (p @@ a) ->+  Decision (q @@ a) ->+  Decision ((p ||| q) @@ a) decideOr = \case-    Proved p    -> \_ -> Proved $ Left p-    Disproved v -> mapDecision Right (either (absurd . v) id)+  Proved p -> \_ -> Proved $ Left p+  Disproved v -> mapDecision Right (either (absurd . v) id)  -- | Left-biased "or".  In proofs, prioritize a proof of the left side over -- a proof of the right side.@@ -104,78 +131,87 @@ type p ^^^ q = (p &&& Not q) ||| (Not p &&& q)  -- | Decide @p '^^^' q@ based on decisions of @p@ and @q@.-decideXor-    :: forall p q a. ()-    => Decision (p @@ a)-    -> Decision (q @@ a)-    -> Decision ((p ^^^ q) @@ a)-decideXor p q = decideOr @(p &&& Not q) @(Not p &&& q) @a-                  (decideAnd @p @(Not q) @a p (decideNot @q @a q))-                  (decideAnd @(Not p) @q @a (decideNot @p @a p) q)+decideXor ::+  forall p q a.+  () =>+  Decision (p @@ a) ->+  Decision (q @@ a) ->+  Decision ((p ^^^ q) @@ a)+decideXor p q =+  decideOr @(p &&& Not q) @(Not p &&& q) @a+    (decideAnd @p @(Not q) @a p (decideNot @q @a q))+    (decideAnd @(Not p) @q @a (decideNot @p @a p) q)  -- | @p ==> q@ is true if @q@ is provably true under the condition that @p@ -- is true. data (==>) :: Predicate k -> Predicate k -> Predicate k+ type instance Apply (p ==> q) a = p @@ a -> q @@ a  infixr 1 ==> -instance Decidable (Impossible ==> p) where+instance Decidable (Impossible ==> p) instance Provable (Impossible ==> p) where-    prove = explosion @p+  prove = explosion @p  instance (Decidable (p ==> q), Decidable q) => Decidable (Not q ==> Not p) where-    decide x = case decide @(p ==> q) x of-      Proved pq     -> Proved $ \vq p -> vq (pq p)-      Disproved vpq -> case decide @q x of-        Proved    q  -> Disproved $ \_     -> vpq (const q)-        Disproved vq -> Disproved $ \vnpnq -> vpq (absurd . vnpnq vq)+  decide x = case decide @(p ==> q) x of+    Proved pq -> Proved $ \vq p -> vq (pq p)+    Disproved vpq -> case decide @q x of+      Proved q -> Disproved $ \_ -> vpq (const q)+      Disproved vq -> Disproved $ \vnpnq -> vpq (absurd . vnpnq vq) instance Provable (p ==> q) => Provable (Not q ==> Not p) where-    prove = contrapositive @p @q (prove @(p ==> q))+  prove = contrapositive @p @q (prove @(p ==> q))  -- | @since 0.1.1.0-instance {-# OVERLAPPING #-} Decidable (p &&& q ==> p) where+instance {-# OVERLAPPING #-} Decidable (p &&& q ==> p)+ -- | @since 0.1.1.0 instance {-# OVERLAPPING #-} Provable (p &&& q ==> p) where-    prove = projAndFst @p @q+  prove = projAndFst @p @q  -- | @since 0.1.1.0-instance {-# OVERLAPPING #-} Decidable (p &&& q ==> q) where+instance {-# OVERLAPPING #-} Decidable (p &&& q ==> q)+ -- | @since 0.1.1.0 instance {-# OVERLAPPING #-} Provable (p &&& q ==> q) where-    prove = projAndSnd @p @q+  prove = projAndSnd @p @q  -- | @since 0.1.1.0-instance {-# OVERLAPPING #-} Decidable (p &&& p ==> p) where+instance {-# OVERLAPPING #-} Decidable (p &&& p ==> p)+ -- | @since 0.1.1.0 instance {-# OVERLAPPING #-} Provable (p &&& p ==> p) where-    prove = projAndFst @p @p+  prove = projAndFst @p @p  -- | @since 0.1.1.0 instance {-# OVERLAPPING #-} Decidable (p ==> p ||| q)+ -- | @since 0.1.1.0 instance {-# OVERLAPPING #-} Provable (p ==> p ||| q) where-    prove = injOrLeft @p @q+  prove = injOrLeft @p @q  -- | @since 0.1.1.0 instance {-# OVERLAPPING #-} Decidable (q ==> p ||| q)+ -- | @since 0.1.1.0 instance {-# OVERLAPPING #-} Provable (q ==> p ||| q) where-    prove = injOrRight @p @q+  prove = injOrRight @p @q  -- | @since 0.1.1.0 instance {-# OVERLAPPING #-} Decidable (p ==> p ||| p)+ -- | @since 0.1.1.0 instance {-# OVERLAPPING #-} Provable (p ==> p ||| p) where-    prove = injOrLeft @p @p+  prove = injOrLeft @p @p  -- | @'Implies' p q@ is a constraint that @p '==>' q@ is 'Provable'; that -- is, you can prove that @p@ implies @q@.-type Implies  p q = Provable  (p ==> q)+type Implies p q = Provable (p ==> q)  -- | @'Equiv' p q@ is a constraint that @p '<==>' q@ is 'Provable'; that -- is, you can prove that @p@ is logically equivalent to @q@.-type Equiv  p q = Provable  (p <==> q)+type Equiv p q = Provable (p <==> q)  -- | If @q@ is provable, then so is @p '==>' q@. --@@ -193,7 +229,8 @@ proveImplies q x _ = q x  -- | Two-way implication, or logical equivalence-type (p <==> q) = p ==> q &&& q ==> p+type p <==> q = p ==> q &&& q ==> p+ infixr 1 <==>  -- | From @'Impossible' @@ a@, you can prove anything.  Essentially@@ -215,23 +252,24 @@  -- | @since 0.1.3.0 instance {-# OVERLAPPING #-} Provable (p &&& Not p ==> Impossible) where-    prove = complementation @p+  prove = complementation @p  -- | If p implies q, then not q implies not p.-contrapositive-    :: (p --> q)-    -> (Not q --> Not p)+contrapositive ::+  (p --> q) ->+  (Not q --> Not p) contrapositive f x vQ p = vQ (f x p)  -- | Reverse direction of 'contrapositive'.  Only possible if @q@ is -- 'Decidable' on its own, without the help of @p@, which makes this much -- less useful.-contrapositive'-    :: forall p q. Decidable q-    => (Not q --> Not p)-    -> (p --> q)+contrapositive' ::+  forall p q.+  Decidable q =>+  (Not q --> Not p) ->+  (p --> q) contrapositive' f x p = elimDisproof (decide @q x) $ \vQ ->-    f x vQ p+  f x vQ p  -- | Logical double negation.  Only possible if @p@ is 'Decidable'. --@@ -240,7 +278,7 @@ -- p)) implies not p (see 'tripleNegation') doubleNegation :: forall p. Decidable p => Not (Not p) --> p doubleNegation x vvP = elimDisproof (decide @p x) $ \vP ->-    vvP vP+  vvP vP  -- | In constructivist logic, not (not (not p)) implies not p. --
src/Data/Type/Predicate/Param.hs view
@@ -1,13 +1,14 @@-{-# LANGUAGE ConstraintKinds      #-}-{-# LANGUAGE FlexibleContexts     #-}-{-# LANGUAGE FlexibleInstances    #-}-{-# LANGUAGE GADTs                #-}-{-# LANGUAGE LambdaCase           #-}-{-# LANGUAGE ScopedTypeVariables  #-}-{-# LANGUAGE TypeApplications     #-}-{-# LANGUAGE TypeFamilies         #-}-{-# LANGUAGE TypeInType           #-}-{-# LANGUAGE TypeOperators        #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-}  -- |@@ -21,33 +22,49 @@ -- -- Manipulate "parameterized predicates".  See 'ParamPred' and 'Found' for -- more information.--- module Data.Type.Predicate.Param (   -- * Parameterized Predicates-    ParamPred-  , IsTC, EqBy-  , FlipPP, ConstPP, PPMap, PPMapV, InP, AnyMatch, TyPP+  ParamPred,+  IsTC,+  EqBy,+  FlipPP,+  ConstPP,+  PPMap,+  PPMapV,+  InP,+  AnyMatch,+  TyPP,+   -- * Deciding and Proving-  , Found, NotFound-  , Selectable, select-  , Searchable, search-  , inPNotNull, notNullInP+  Found,+  NotFound,+  Selectable,+  select,+  Searchable,+  search,+  inPNotNull,+  notNullInP,+   -- ** Type Constructors-  , SelectableTC, selectTC-  , SearchableTC, searchTC+  SelectableTC,+  selectTC,+  SearchableTC,+  searchTC,+   -- * Combining-  , OrP, AndP-  ) where+  OrP,+  AndP,+) where -import           Data.Kind-import           Data.Singletons-import           Data.Singletons.Decide-import           Data.Singletons.Sigma-import           Data.Tuple.Singletons-import           Data.Type.Functor.Product-import           Data.Type.Predicate-import           Data.Type.Predicate.Logic-import           Data.Type.Universe+import Data.Kind+import Data.Singletons+import Data.Singletons.Decide+import Data.Singletons.Sigma+import Data.Tuple.Singletons+import Data.Type.Functor.Product+import Data.Type.Predicate+import Data.Type.Predicate.Logic+import Data.Type.Universe  -- | A parameterized predicate.  See 'Found' for more information. type ParamPred k v = k -> Predicate v@@ -72,6 +89,7 @@ -- :: k@, we can prove or disprove the fact that there exists a @y :: v@ -- such that @P x \@\@ y@. data Found :: ParamPred k v -> Predicate k+ type instance Apply (Found (p :: ParamPred k v)) a = Σ v (p a)  -- | Convert a parameterized predicate into a predicate on the parameter.@@ -97,11 +115,13 @@  -- | Flip the arguments of a 'ParamPred'. data FlipPP :: ParamPred v k -> ParamPred k v+ type instance Apply (FlipPP p x) y = p y @@ x  -- | Promote a @'Predicate' v@ to a @'ParamPred' k v@, ignoring the @k@ -- input. data ConstPP :: Predicate v -> ParamPred k v+ type instance Apply (ConstPP p k) v = p @@ v  -- | @Found ('EqBy' f) \@\@ x@ is true if there exists some value when,@@ -116,6 +136,7 @@ -- -- @since 0.1.5.0 data EqBy :: (v ~> k) -> ParamPred k v+ type instance Apply (EqBy f x) y = x :~: (f @@ y)  -- | @Found ('IsTC' t) \@\@ x@ is true if @x@ was made using the unary type@@ -158,29 +179,34 @@ -- -- @since 0.1.4.0 data TyPP :: (k -> v -> Type) -> ParamPred k v+ type instance Apply (TyPP t k) v = t k v  -- | Pre-compose a function to a 'ParamPred'.  Is essentially @'flip' -- ('.')@, but unfortunately defunctionalization doesn't work too well with -- that definition. data PPMap :: (k ~> j) -> ParamPred j v -> ParamPred k v+ type instance Apply (PPMap f p x) y = p (f @@ x) @@ y  -- | Pre-compose a function to a 'ParamPred', but on the "value" side. -- -- @since 0.1.5.0 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 = mapDecision (\case i :&: p -> i :&: p)-                         (\case i :&: p -> i :&: p)-           . decide @(Found p)-           . applySing (sing :: Sing f)     -- can just be sing @f in singletons 2.5, ghc 8.6++  decide =+    mapDecision+      (\case i :&: p -> i :&: p)+      (\case i :&: p -> i :&: p)+      . decide @(Found p)+      . applySing (sing :: Sing f) -- can just be sing @f in singletons 2.5, ghc 8.6+  instance (Provable (Found (p :: ParamPred j v)), SingI (f :: k ~> j)) => Provable (Found (PPMap f p)) where-    prove (x :: Sing a) = case prove @(Found p) ((sing :: Sing f) @@ x) of-        i :&: p -> i :&: p+  prove (x :: Sing a) = case prove @(Found p) ((sing :: Sing f) @@ x) of+    i :&: p -> i :&: p  -- | A constraint that a @'ParamPred' k v@ is "searchable".  It means that -- for any input @x :: k@, we can prove or disprove that there exists a @y@@ -191,7 +217,7 @@ -- | A constraint that a @'ParamPred' k v@ s "selectable".  It means that -- for any input @x :: k@, we can always find a @y :: v@ that satisfies @P -- x \@\@ y@.  We can "select" that @y@, no matter what.-type Selectable p = Provable  (Found p)+type Selectable p = Provable (Found p)  -- | The deciding/searching function for @'Searchable' p@. --@@ -204,9 +230,10 @@ -- -- See 'searchTC' and 'SearchableTC' for a version that isn't ambiguously -- typed, but only works when @p@ is a type constructor.-search-    :: forall p. Searchable p-    => Decide (Found p)+search ::+  forall p.+  Searchable p =>+  Decide (Found p) search = decide @(Found p)  -- | The proving/selecting function for @'Selectable' p@.@@ -220,9 +247,10 @@ -- -- See 'selectTC' and 'SelectableTC' for a version that isn't ambiguously -- typed, but only works when @p@ is a type constructor.-select-    :: forall p. Selectable p-    => Prove (Found p)+select ::+  forall p.+  Selectable p =>+  Prove (Found p) select = prove @(Found p)  -- | If @T :: k -> v -> 'Type'@ is a type constructor, then @'SearchableTC'@@ -261,7 +289,7 @@ -- TypeApplications to use. -- -- @since 0.1.4.0-type SelectableTC t = Provable  (Found (TyPP t))+type SelectableTC t = Provable (Found (TyPP t))  -- | The canonical selecting function for @'Searchable' t@. --@@ -270,9 +298,10 @@ -- can be inferred from the result type. -- -- @since 0.1.4.0-searchTC-    :: forall t. SearchableTC t-    => Decide (Found (TyPP t))+searchTC ::+  forall t.+  SearchableTC t =>+  Decide (Found (TyPP t)) searchTC = search @(TyPP t)  -- | The canonical selecting function for @'SelectableTC' t@.@@ -282,9 +311,10 @@ -- can be inferred from the result type. -- -- @since 0.1.4.0-selectTC-    :: forall t. SelectableTC t-    => Prove (Found (TyPP t))+selectTC ::+  forall t.+  SelectableTC t =>+  Prove (Found (TyPP t)) selectTC = select @(TyPP t)  -- | A @'ParamPred' (f k) k@.  Parameterized on an @as :: f k@, returns@@ -306,17 +336,19 @@ inPNotNull _ (s :&: i) = WitAny i s  instance Universe f => Decidable (Found (InP f)) where-    decide = mapDecision (\case WitAny i s -> s :&: i    )-                         (\case s :&: i     -> WitAny i s)-           . decide @(NotNull f)+  decide =+    mapDecision+      (\case WitAny i s -> s :&: i)+      (\case s :&: i -> WitAny i s)+      . decide @(NotNull f)  instance Decidable (NotNull f ==> Found (InP f)) instance Provable (NotNull f ==> Found (InP f)) where-    prove = notNullInP+  prove = notNullInP  instance Decidable (Found (InP f) ==> NotNull f) instance Provable (Found (InP f) ==> NotNull f) where-    prove = inPNotNull+  prove = inPNotNull  -- | @'AnyMatch' f@ takes a parmaeterized predicate on @k@ (testing for -- a @v@) and turns it into a parameterized predicate on @f k@ (testing for@@ -329,18 +361,22 @@ -- A @'ParamPred' k v@ tests if a @k@ can create some @v@.  The resulting -- @'ParamPred' (f k) v@ tests if any @k@ in @f k@ can create some @v@. 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 = mapDecision (\case WitAny i (x :&: p) -> x :&: WitAny i p  )-                         (\case x :&: WitAny i p   -> WitAny i (x :&: p))-           . decide @(Any f (Found p))+  decide =+    mapDecision+      (\case WitAny i (x :&: p) -> x :&: WitAny i p)+      (\case x :&: WitAny i p -> WitAny i (x :&: p))+      . decide @(Any f (Found p))  -- | Disjunction on two 'ParamPred's, with appropriate 'Searchable' -- instance.  Priority is given to the left predicate. -- -- @since 0.1.3.0 data OrP :: ParamPred k v -> ParamPred k v -> ParamPred k v+ type instance Apply (OrP p q x) y = (p x ||| q x) @@ y  -- | Conjunction on two 'ParamPred's, with appropriate 'Searchable' and@@ -348,27 +384,28 @@ -- -- @since 0.1.3.0 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 x = case search @p x of-      Proved (s :&: p) -> Proved $ s :&: Left p-      Disproved vp     -> case search @q x of-        Proved (s :&: q) -> Proved $ s :&: Right q-        Disproved vq     -> Disproved $ \case-          s :&: Left  p -> vp (s :&: p)-          s :&: Right q -> vq (s :&: q)+  decide x = case search @p x of+    Proved (s :&: p) -> Proved $ s :&: Left p+    Disproved vp -> case search @q x of+      Proved (s :&: q) -> Proved $ s :&: Right q+      Disproved vq -> Disproved $ \case+        s :&: Left p -> vp (s :&: p)+        s :&: Right q -> vq (s :&: q)  instance (Searchable p, Searchable q) => Decidable (Found (AndP p q)) where-    decide x = case search @p x of-      Proved (s :&: p) -> case search @q x of-        Proved (t :&: q) -> Proved $ STuple2 s t :&: (p, q)-        Disproved vq     -> Disproved $ \case-          STuple2 _ t :&: (_, q) -> vq $ t :&: q-      Disproved vp     -> Disproved $ \case-        STuple2 s _ :&: (p, _) -> vp $ s :&: p+  decide x = case search @p x of+    Proved (s :&: p) -> case search @q x of+      Proved (t :&: q) -> Proved $ STuple2 s t :&: (p, q)+      Disproved vq -> Disproved $ \case+        STuple2 _ t :&: (_, q) -> vq $ t :&: q+    Disproved vp -> Disproved $ \case+      STuple2 s _ :&: (p, _) -> vp $ s :&: p  instance (Selectable p, Selectable q) => Provable (Found (AndP p q)) where-    prove x = case select @p x of-        s :&: p -> case select @q x of-          t :&: q -> STuple2 s t :&: (p, q)+  prove x = case select @p x of+    s :&: p -> case select @q x of+      t :&: q -> STuple2 s t :&: (p, q)
src/Data/Type/Predicate/Quantification.hs view
@@ -1,10 +1,11 @@-{-# LANGUAGE LambdaCase          #-}-{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications    #-}-{-# LANGUAGE TypeFamilies        #-}-{-# LANGUAGE TypeInType          #-}-{-# LANGUAGE TypeOperators       #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}  -- | -- Module      : Data.Type.Predicate.Quantification@@ -17,40 +18,66 @@ -- -- Higher-level predicates for quantifying predicates over universes and -- sets.--- module Data.Type.Predicate.Quantification (   -- * Any-    Any, WitAny(..), None, anyImpossible+  Any,+  WitAny (..),+  None,+  anyImpossible,+   -- ** Decision-  , decideAny, idecideAny, decideNone, idecideNone+  decideAny,+  idecideAny,+  decideNone,+  idecideNone,+   -- ** Entailment-  , entailAny, ientailAny, entailAnyF, ientailAnyF+  entailAny,+  ientailAny,+  entailAnyF,+  ientailAnyF,+   -- * All-  , All, WitAll(..), NotAll+  All,+  WitAll (..),+  NotAll,+   -- ** Decision-  , decideAll, idecideAll+  decideAll,+  idecideAll,+   -- ** Entailment-  , entailAll, ientailAll, entailAllF, ientailAllF-  , decideEntailAll, idecideEntailAll+  entailAll,+  ientailAll,+  entailAllF,+  ientailAllF,+  decideEntailAll,+  idecideEntailAll,+   -- * Logical interplay-  , allToAny-  , allNotNone, noneAllNot-  , anyNotNotAll, notAllAnyNot-  ) where+  allToAny,+  allNotNone,+  noneAllNot,+  anyNotNotAll,+  notAllAnyNot,+) where -import           Data.Kind-import           Data.Singletons-import           Data.Singletons.Decide-import           Data.Type.Functor.Product-import           Data.Type.Predicate-import           Data.Type.Predicate.Logic-import           Data.Type.Universe+import Data.Kind+import Data.Singletons+import Data.Singletons.Decide+import Data.Type.Functor.Product+import Data.Type.Predicate+import Data.Type.Predicate.Logic+import Data.Type.Universe  -- | 'decideNone', but providing an 'Elem'.-idecideNone-    :: forall f k (p :: k ~> Type) (as :: f k). Universe f-    => (forall a. Elem f as a -> Sing a -> Decision (p @@ a))    -- ^ predicate on value-    -> (Sing as -> Decision (None f p @@ as))                    -- ^ predicate on collection+idecideNone ::+  forall f k (p :: k ~> Type) (as :: f k).+  Universe f =>+  -- | predicate on value+  (forall a. Elem f as a -> Sing a -> Decision (p @@ a)) ->+  -- | predicate on collection+  (Sing as -> Decision (None f p @@ as)) idecideNone f xs = decideNot @(Any f p) $ idecideAny f xs  -- | Lifts a predicate @p@ on an individual @a@ into a predicate that on@@ -59,50 +86,61 @@ -- -- That is, it turns a predicate of kind @k ~> Type@ into a predicate -- of kind @f k ~> Type@.-decideNone-    :: forall f k (p :: k ~> Type). Universe f-    => Decide p                         -- ^ predicate on value-    -> Decide (None f p)                -- ^ predicate on collection+decideNone ::+  forall f k (p :: k ~> Type).+  Universe f =>+  -- | predicate on value+  Decide p ->+  -- | predicate on collection+  Decide (None f p) decideNone f = idecideNone (const f)  -- | 'entailAny', but providing an 'Elem'.-ientailAny-    :: forall f p q as. (Universe f, SingI as)-    => (forall a. Elem f as a -> Sing a -> p @@ a -> q @@ a)        -- ^ implication-    -> Any f p @@ as-    -> Any f q @@ as+ientailAny ::+  forall f p q as.+  (Universe f, SingI as) =>+  -- | implication+  (forall a. Elem f as a -> Sing a -> p @@ a -> q @@ a) ->+  Any f p @@ as ->+  Any f q @@ as ientailAny f (WitAny i x) = WitAny i (f i (indexSing i sing) x)  -- | If there exists an @a@ s.t. @p a@, and if @p@ implies @q@, then there -- must exist an @a@ s.t. @q a@.-entailAny-    :: forall f p q. Universe f-    => (p --> q)-    -> (Any f p --> Any f q)+entailAny ::+  forall f p q.+  Universe f =>+  (p --> q) ->+  (Any f p --> Any f q) entailAny = tmap @(Any f)  -- | 'entailAll', but providing an 'Elem'.-ientailAll-    :: forall f p q as. (Universe f, SingI as)-    => (forall a. Elem f as a -> Sing a -> p @@ a -> q @@ a)      -- ^ implication-    -> All f p @@ as-    -> All f q @@ as+ientailAll ::+  forall f p q as.+  (Universe f, SingI as) =>+  -- | implication+  (forall a. Elem f as a -> Sing a -> p @@ a -> q @@ a) ->+  All f p @@ as ->+  All f q @@ as ientailAll f a = WitAll $ \i -> f i (indexSing i sing) (runWitAll a i)  -- | If for all @a@ we have @p a@, and if @p@ implies @q@, then for all @a@ -- we must also have @p a@.-entailAll-    :: forall f p q. Universe f-    => (p --> q)-    -> (All f p --> All f q)+entailAll ::+  forall f p q.+  Universe f =>+  (p --> q) ->+  (All f p --> All f q) entailAll = tmap @(All f)  -- | 'entailAnyF', but providing an 'Elem'.-ientailAnyF-    :: forall f p q as h. Functor h-    => (forall a. Elem f as a -> p @@ a -> h (q @@ a))      -- ^ implication in context-    -> Any f p @@ as-    -> h (Any f q @@ as)+ientailAnyF ::+  forall f p q as h.+  Functor h =>+  -- | implication in context+  (forall a. Elem f as a -> p @@ a -> h (q @@ a)) ->+  Any f p @@ as ->+  h (Any f q @@ as) ientailAnyF f = \case WitAny i x -> WitAny i <$> f i x  -- | If @p@ implies @q@ under some context @h@, and if there exists some@@ -116,46 +154,58 @@ -- This is if the @p a -> 'Decision' (q a)@ implication is false, there -- it doesn't mean that there is /no/ @a@ such that @q a@, necessarily. -- There could have been an @a@ where @p@ does not hold, but @q@ does.-entailAnyF-    :: forall f p q h. (Universe f, Functor h)-    => (p --># q) h                                     -- ^ implication in context-    -> (Any f p --># Any f q) h-entailAnyF f x a = withSingI x $+entailAnyF ::+  forall f p q h.+  (Universe f, Functor h) =>+  -- | implication in context+  (p --># q) h ->+  (Any f p --># Any f q) h+entailAnyF f x a =+  withSingI x $     ientailAnyF @f @p @q (\i -> f (indexSing i x)) a  -- | 'entailAllF', but providing an 'Elem'.-ientailAllF-    :: forall f p q as h. (Universe f, Applicative h, SingI as)-    => (forall a. Elem f as a -> p @@ a -> h (q @@ a))    -- ^ implication in context-    -> All f p @@ as-    -> h (All f q @@ as)-ientailAllF f a = fmap (prodAll getWit)-                . itraverseProd (\i _ -> Wit @q <$> f i (runWitAll a i))-                $ singProd (sing @as)+ientailAllF ::+  forall f p q as h.+  (Universe f, Applicative h, SingI as) =>+  -- | implication in context+  (forall a. Elem f as a -> p @@ a -> h (q @@ a)) ->+  All f p @@ as ->+  h (All f q @@ as)+ientailAllF f a =+  fmap (prodAll getWit)+    . itraverseProd (\i _ -> Wit @q <$> f i (runWitAll a i))+    $ singProd (sing @as)  -- | If @p@ implies @q@ under some context @h@, and if we have @p a@ for -- all @a@, then we must have @q a@ for all @a@ under context @h@.-entailAllF-    :: forall f p q h. (Universe f, Applicative h)-    => (p --># q) h                                     -- ^ implication in context-    -> (All f p --># All f q) h-entailAllF f x a = withSingI x $+entailAllF ::+  forall f p q h.+  (Universe f, Applicative h) =>+  -- | implication in context+  (p --># q) h ->+  (All f p --># All f q) h+entailAllF f x a =+  withSingI x $     ientailAllF @f @p @q (\i -> f (indexSing i x)) a  -- | 'entailAllF', but providing an 'Elem'.-idecideEntailAll-    :: forall f p q as. (Universe f, SingI as)-    => (forall a. Elem f as a -> p @@ a -> Decision (q @@ a))     -- ^ decidable implication-    -> All f p @@ as-    -> Decision (All f q @@ as)+idecideEntailAll ::+  forall f p q as.+  (Universe f, SingI as) =>+  -- | decidable implication+  (forall a. Elem f as a -> p @@ a -> Decision (q @@ a)) ->+  All f p @@ as ->+  Decision (All f q @@ as) idecideEntailAll f a = idecideAll (\i _ -> f i (runWitAll a i)) sing  -- | If we have @p a@ for all @a@, and @p a@ can be used to test for @q a@, -- then we can test all @a@s for @q a@.-decideEntailAll-    :: forall f p q. Universe f-    => p -?> q-    -> All f p -?> All f q+decideEntailAll ::+  forall f p q.+  Universe f =>+  p -?> q ->+  All f p -?> All f q decideEntailAll = dmap @(All f)  -- | It is impossible for any value in a collection to be 'Impossible'.@@ -176,13 +226,14 @@ -- order to locate that specific @a@. -- -- @since 0.1.2.0-notAllAnyNot-    :: forall f p. (Universe f, Decidable p)-    => NotAll f p --> Any f (Not p)+notAllAnyNot ::+  forall f p.+  (Universe f, Decidable p) =>+  NotAll f p --> Any f (Not p) notAllAnyNot xs vAll = elimDisproof (decide @(Any f (Not p)) xs) $ \vAny ->-    vAll $ WitAll $ \i ->-      elimDisproof (decide @p (indexSing i xs)) $ \vP ->-        vAny $ WitAny i vP+  vAll $ WitAll $ \i ->+    elimDisproof (decide @p (indexSing i xs)) $ \vP ->+      vAny $ WitAny i vP  -- | If @p@ is false for all @a@ in @as@, then no @a@ in @as@ satisfies -- @p@.@@ -195,11 +246,12 @@ -- @as@.  Requires @'Decidable' p@ to interrogate the input disproof. -- -- @since 0.1.2.0-noneAllNot-    :: forall f p. (Universe f, Decidable p)-    => None f p --> All f (Not p)+noneAllNot ::+  forall f p.+  (Universe f, Decidable p) =>+  None f p --> All f (Not p) noneAllNot xs vAny = elimDisproof (decide @(All f (Not p)) xs) $ \vAll ->-    vAll $ WitAll $ \i p -> vAny $ WitAny i p+  vAll $ WitAll $ \i p -> vAny $ WitAny i p  -- | If something is true for all xs, then it must be true for at least one -- x in xs, provided that xs is not empty.
src/Data/Type/Universe.hs view
@@ -1,21 +1,16 @@-{-# LANGUAGE CPP                    #-}-{-# LANGUAGE DeriveDataTypeable     #-}-{-# LANGUAGE DeriveFunctor          #-}-{-# LANGUAGE DeriveGeneric          #-}-{-# LANGUAGE DeriveTraversable      #-}-{-# LANGUAGE EmptyCase              #-}-{-# LANGUAGE FlexibleInstances      #-}-{-# LANGUAGE GADTs                  #-}-{-# LANGUAGE InstanceSigs           #-}-{-# LANGUAGE LambdaCase             #-}-{-# LANGUAGE RankNTypes             #-}-{-# LANGUAGE ScopedTypeVariables    #-}-{-# LANGUAGE StandaloneDeriving     #-}-{-# LANGUAGE TemplateHaskell        #-}-{-# LANGUAGE TypeApplications       #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE EmptyCase #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilyDependencies #-}-{-# LANGUAGE TypeInType             #-}-{-# LANGUAGE TypeOperators          #-}+{-# LANGUAGE TypeOperators #-}  -- | -- Module      : Data.Type.Universe@@ -28,47 +23,75 @@ -- -- A type family for "containers", intended for allowing lifting of -- predicates on @k@ to be predicates on containers @f k@.--- module Data.Type.Universe (   -- * Universe-    Elem, In, Universe(..)-  , singAll+  Elem,+  In,+  Universe (..),+  singAll,+   -- ** Instances-  , Index(..), IJust(..), IRight(..), NEIndex(..), ISnd(..), IIdentity(..)+  Index (..),+  IJust (..),+  IRight (..),+  NEIndex (..),+  ISnd (..),+  IIdentity (..),+   -- ** Predicates-  , All, WitAll(..), NotAll-  , Any, WitAny(..), None-  , Null, NotNull+  All,+  WitAll (..),+  NotAll,+  Any,+  WitAny (..),+  None,+  Null,+  NotNull,+   -- *** Specialized-  , IsJust, IsNothing, IsRight, IsLeft+  IsJust,+  IsNothing,+  IsRight,+  IsLeft,+   -- * Decisions and manipulations-  , decideAny, decideAll-  , genAll, igenAll-  , splitSing-  , pickElem-  ) where+  decideAny,+  decideAll,+  genAll,+  igenAll,+  splitSing,+  pickElem,+) where -import           Data.Either.Singletons hiding    (IsLeft, IsRight)-import           Data.Functor.Identity-import           Data.Functor.Identity.Singletons-import           Data.Kind-import           Data.List.NonEmpty               (NonEmpty(..))-import           Data.List.Singletons hiding      (Elem, ElemSym0, ElemSym1, ElemSym2, All, Any, Null)-import           Data.Maybe.Singletons hiding     (IsJust, IsNothing)-import           Data.Singletons-import           Data.Singletons.Decide-import           Data.Tuple.Singletons-import           Data.Type.Functor.Product-import           Data.Type.Predicate-import           Data.Type.Predicate.Logic-import           GHC.Generics                     ((:*:)(..))-import           Prelude hiding                   (any, all)-import qualified Data.List.NonEmpty.Singletons    as NE+import Data.Either.Singletons hiding (IsLeft, IsRight)+import Data.Functor.Identity+import Data.Functor.Identity.Singletons+import Data.Kind+import Data.List.NonEmpty (NonEmpty (..))+import qualified Data.List.NonEmpty.Singletons as NE+import Data.List.Singletons hiding (+  All,+  Any,+  Elem,+  ElemSym0,+  ElemSym1,+  ElemSym2,+  Null,+ )+import Data.Maybe.Singletons hiding (IsJust, IsNothing)+import Data.Singletons+import Data.Singletons.Decide+import Data.Tuple.Singletons+import Data.Type.Functor.Product+import Data.Type.Predicate+import Data.Type.Predicate.Logic+import GHC.Generics ((:*:) (..))+import Prelude hiding (all, any)  -- | A @'WitAny' p as@ is a witness that, for at least one item @a@ in the -- type-level collection @as@, the predicate @p a@ is true. data WitAny f :: (k ~> Type) -> f k -> Type where-    WitAny :: Elem f as a -> p @@ a -> WitAny f p as+  WitAny :: Elem f as a -> p @@ a -> WitAny f p as  -- | An @'Any' f p@ is a predicate testing a collection @as :: f a@ for the -- fact that at least one item in @as@ satisfies @p@.  Represents the@@ -77,11 +100,12 @@ -- This is mostly useful for its 'Decidable' and 'TFunctor' instances, -- which lets you lift predicates on @p@ to predicates on @'Any' f p@. data Any f :: Predicate k -> Predicate (f k)+ type instance Apply (Any f p) as = WitAny f p as  -- | A @'WitAll' p as@ is a witness that the predicate @p a@ is true for all -- items @a@ in the type-level collection @as@.-newtype WitAll f p (as :: f k) = WitAll { runWitAll :: forall a. Elem f as a -> p @@ a }+newtype WitAll f p (as :: f k) = WitAll {runWitAll :: forall a. Elem f as a -> p @@ a}  -- | An @'All' f p@ is a predicate testing a collection @as :: f a@ for the -- fact that /all/ items in @as@ satisfy @p@.  Represents the "forall"@@ -91,60 +115,68 @@ -- instances, which lets you lift predicates on @p@ to predicates on @'All' -- f p@. data All f :: Predicate k -> Predicate (f k)+ type instance Apply (All f p) as = WitAll f p as  instance (Universe f, Decidable p) => Decidable (Any f p) where-    decide = decideAny @f @_ @p $ decide @p+  decide = decideAny @f @_ @p $ decide @p  instance (Universe f, Decidable p) => Decidable (All f p) where-    decide = decideAll @f @_ @p $ decide @p+  decide = decideAll @f @_ @p $ decide @p -instance (Universe f, Provable p) => Decidable (NotNull f ==> Any f p) where+instance (Universe f, Provable p) => Decidable (NotNull f ==> Any f p)  instance Provable p => Provable (NotNull f ==> Any f p) where-    prove _ (WitAny i s) = WitAny i (prove @p s)+  prove _ (WitAny i s) = WitAny i (prove @p s)  instance (Universe f, Provable p) => Provable (All f p) where-    prove xs = WitAll $ \i -> prove @p (indexSing i xs)+  prove xs = WitAll $ \i -> prove @p (indexSing i xs)  instance Universe f => TFunctor (Any f) where-    tmap f xs (WitAny i x) = WitAny i (f (indexSing i xs) x)+  tmap f xs (WitAny i x) = WitAny i (f (indexSing i xs) x)  instance Universe f => TFunctor (All f) where-    tmap f xs a = WitAll $ \i -> f (indexSing i xs) (runWitAll a i)+  tmap f xs a = WitAll $ \i -> f (indexSing i xs) (runWitAll a i)  instance Universe f => DFunctor (All f) where-    dmap f xs a = idecideAll (\i x -> f x (runWitAll a i)) xs+  dmap f xs a = idecideAll (\i x -> f x (runWitAll a i)) xs  -- | Typeclass for a type-level container that you can quantify or lift -- type-level predicates over. class FProd f => Universe (f :: Type -> Type) where--    -- | 'decideAny', but providing an 'Elem'.-    idecideAny-        :: forall k (p :: k ~> Type) (as :: f k). ()-        => (forall a. Elem f as a -> Sing a -> Decision (p @@ a))   -- ^ predicate on value-        -> (Sing as -> Decision (Any f p @@ as))                         -- ^ predicate on collection+  -- | 'decideAny', but providing an 'Elem'.+  idecideAny ::+    forall k (p :: k ~> Type) (as :: f k).+    () =>+    -- | predicate on value+    (forall a. Elem f as a -> Sing a -> Decision (p @@ a)) ->+    -- | predicate on collection+    (Sing as -> Decision (Any f p @@ as)) -    -- | 'decideAll', but providing an 'Elem'.-    idecideAll-        :: forall k (p :: k ~> Type) (as :: f k). ()-        => (forall a. Elem f as a -> Sing a -> Decision (p @@ a))   -- ^ predicate on value-        -> (Sing as -> Decision (All f p @@ as))                         -- ^ predicate on collection+  -- | 'decideAll', but providing an 'Elem'.+  idecideAll ::+    forall k (p :: k ~> Type) (as :: f k).+    () =>+    -- | predicate on value+    (forall a. Elem f as a -> Sing a -> Decision (p @@ a)) ->+    -- | predicate on collection+    (Sing as -> Decision (All f p @@ as)) -    allProd-        :: forall p g. ()-        => (forall a. Sing a -> p @@ a -> g a)-        -> All f p --> TyPred (Prod f g)+  allProd ::+    forall p g.+    () =>+    (forall a. Sing a -> p @@ a -> g a) ->+    All f p --> TyPred (Prod f g) -    prodAll-        :: forall p g as. ()-        => (forall a. g a -> p @@ a)-        -> Prod f g as-        -> All f p @@ as+  prodAll ::+    forall p g as.+    () =>+    (forall a. g a -> p @@ a) ->+    Prod f g as ->+    All f p @@ as  -- | Predicate that a given @as :: f k@ is empty and has no items in it.-type Null    f = (None f Evident :: Predicate (f k))+type Null f = (None f Evident :: Predicate (f k))  -- | Predicate that a given @as :: f k@ is not empty, and has at least one -- item in it.@@ -166,10 +198,13 @@ -- of kind @f k ~> Type@. -- -- Essentially tests existential quantification.-decideAny-    :: forall f k (p :: k ~> Type). Universe f-    => Decide p                                 -- ^ predicate on value-    -> Decide (Any f p)                -- ^ predicate on collection+decideAny ::+  forall f k (p :: k ~> Type).+  Universe f =>+  -- | predicate on value+  Decide p ->+  -- | predicate on collection+  Decide (Any f p) decideAny f = idecideAny (const f)  -- | Lifts a predicate @p@ on an individual @a@ into a predicate that on@@ -180,59 +215,73 @@ -- of kind @f k ~> Type@. -- -- Essentially tests universal quantification.-decideAll-    :: forall f k (p :: k ~> Type). Universe f-    => Decide p                                 -- ^ predicate on value-    -> Decide (All f p)                -- ^ predicate on collection+decideAll ::+  forall f k (p :: k ~> Type).+  Universe f =>+  -- | predicate on value+  Decide p ->+  -- | predicate on collection+  Decide (All f p) decideAll f = idecideAll (const f)  -- | Split a @'Sing' as@ into a proof that all @a@ in @as@ exist.-splitSing-    :: forall f k (as :: f k). Universe f-    => Sing as-    -> All f (TyPred Sing) @@ as+splitSing ::+  forall f k (as :: f k).+  Universe f =>+  Sing as ->+  All f (TyPred Sing) @@ as splitSing = prodAll id . singProd  -- | Automatically generate a witness for a member, if possible-pickElem-    :: forall f k (as :: f k) a. (Universe f, SingI as, SingI a, SDecide k)-    => Decision (Elem f as a)-pickElem = mapDecision (\case WitAny i Refl -> i)-                       (\case i -> WitAny i Refl)-         . decide @(Any f (TyPred ((:~:) a)))-         $ sing+pickElem ::+  forall f k (as :: f k) a.+  (Universe f, SingI as, SingI a, SDecide k) =>+  Decision (Elem f as a)+pickElem =+  mapDecision+    (\case WitAny i Refl -> i)+    (\case i -> WitAny i Refl)+    . decide @(Any f (TyPred ((:~:) a)))+    $ sing  -- | 'genAll', but providing an 'Elem'.-igenAll-    :: forall f k (p :: k ~> Type) (as :: f k). Universe f-    => (forall a. Elem f as a -> Sing a -> p @@ a)            -- ^ always-true predicate on value-    -> (Sing as -> All f p @@ as)                                  -- ^ always-true predicate on collection+igenAll ::+  forall f k (p :: k ~> Type) (as :: f k).+  Universe f =>+  -- | always-true predicate on value+  (forall a. Elem f as a -> Sing a -> p @@ a) ->+  -- | always-true predicate on collection+  (Sing as -> All f p @@ as) igenAll f = prodAll (\(i :*: x) -> f i x) . imapProd (:*:) . singProd  -- | If @p a@ is true for all values @a@ in @as@, then we have @'All' -- p as@.  Basically witnesses the definition of 'All'.-genAll-    :: forall f k (p :: k ~> Type). Universe f-    => Prove p                 -- ^ always-true predicate on value-    -> Prove (All f p)         -- ^ always-true predicate on collection+genAll ::+  forall f k (p :: k ~> Type).+  Universe f =>+  -- | always-true predicate on value+  Prove p ->+  -- | always-true predicate on collection+  Prove (All f p) genAll f = prodAll f . singProd  -- | Split a @'Sing' as@ into a proof that all @a@ in @as@ exist.-singAll-    :: forall f k (as :: f k). Universe f-    => Sing as-    -> All f Evident @@ as+singAll ::+  forall f k (as :: f k).+  Universe f =>+  Sing as ->+  All f Evident @@ as singAll = prodAll id . singProd  -- | Test that a 'Maybe' is 'Just'. -- -- @since 0.1.2.0-type IsJust    = (NotNull Maybe :: Predicate (Maybe k))+type IsJust = (NotNull Maybe :: Predicate (Maybe k))  -- | Test that a 'Maybe' is 'Nothing'. -- -- @since 0.1.2.0-type IsNothing = (Null    Maybe :: Predicate (Maybe k))+type IsNothing = (Null Maybe :: Predicate (Maybe k))  -- | Test that an 'Either' is 'Right' --@@ -242,168 +291,178 @@ -- | Test that an 'Either' is 'Left' -- -- @since 0.1.2.0-type IsLeft  = (Null    (Either j) :: Predicate (Either j k))-+type IsLeft = (Null (Either j) :: Predicate (Either j k))  instance Universe [] where-    idecideAny-        :: forall k (p :: k ~> Type) (as :: [k]). ()-        => (forall a. Elem [] as a -> Sing a -> Decision (p @@ a))-        -> Sing as-        -> Decision (Any [] p @@ as)-    idecideAny f = \case-      SNil -> Disproved $ \case-        WitAny i _ -> case i of {}-      x `SCons` xs -> case f IZ x of-        Proved p    -> Proved $ WitAny IZ p-        Disproved v -> case idecideAny @[] @_ @p (f . IS) xs of-          Proved (WitAny i p) -> Proved $ WitAny (IS i) p-          Disproved vs -> Disproved $ \case-            WitAny IZ     p -> v p-            WitAny (IS i) p -> vs (WitAny i p)+  idecideAny ::+    forall k (p :: k ~> Type) (as :: [k]).+    () =>+    (forall a. Elem [] as a -> Sing a -> Decision (p @@ a)) ->+    Sing as ->+    Decision (Any [] p @@ as)+  idecideAny f = \case+    SNil -> Disproved $ \case+      WitAny i _ -> case i of {}+    x `SCons` xs -> case f IZ x of+      Proved p -> Proved $ WitAny IZ p+      Disproved v -> case idecideAny @[] @_ @p (f . IS) xs of+        Proved (WitAny i p) -> Proved $ WitAny (IS i) p+        Disproved vs -> Disproved $ \case+          WitAny IZ p -> v p+          WitAny (IS i) p -> vs (WitAny i p) -    idecideAll-        :: forall k (p :: k ~> Type) (as :: [k]). ()-        => (forall a. Elem [] as a -> Sing a -> Decision (p @@ a))-        -> Sing as-        -> Decision (All [] p @@ as)-    idecideAll f = \case-      SNil -> Proved $ WitAll $ \case {}-      x `SCons` xs -> case f IZ x of-        Proved p -> case idecideAll @[] @_ @p (f . IS) xs of-          Proved a -> Proved $ WitAll $ \case-            IZ   -> p-            IS i -> runWitAll a i-          Disproved v -> Disproved $ \a -> v $ WitAll (runWitAll a . IS)-        Disproved v -> Disproved $ \a -> v $ runWitAll a IZ+  idecideAll ::+    forall k (p :: k ~> Type) (as :: [k]).+    () =>+    (forall a. Elem [] as a -> Sing a -> Decision (p @@ a)) ->+    Sing as ->+    Decision (All [] p @@ as)+  idecideAll f = \case+    SNil -> Proved $ WitAll $ \case {}+    x `SCons` xs -> case f IZ x of+      Proved p -> case idecideAll @[] @_ @p (f . IS) xs of+        Proved a -> Proved $ WitAll $ \case+          IZ -> p+          IS i -> runWitAll a i+        Disproved v -> Disproved $ \a -> v $ WitAll (runWitAll a . IS)+      Disproved v -> Disproved $ \a -> v $ runWitAll a IZ -    allProd-        :: forall p g. ()-        => (forall a. Sing a -> p @@ a -> g a)-        -> All [] p --> TyPred (Prod [] g)-    allProd f = go-      where-        go :: Sing as -> WitAll [] p as -> Prod [] g as-        go = \case-          SNil         -> \_ -> RNil-          x `SCons` xs -> \a -> f x (runWitAll a IZ)-                             :& go xs (WitAll (runWitAll a . IS))+  allProd ::+    forall p g.+    () =>+    (forall a. Sing a -> p @@ a -> g a) ->+    All [] p --> TyPred (Prod [] g)+  allProd f = go+    where+      go :: Sing as -> WitAll [] p as -> Prod [] g as+      go = \case+        SNil -> \_ -> RNil+        x `SCons` xs -> \a ->+          f x (runWitAll a IZ)+            :& go xs (WitAll (runWitAll a . IS)) -    prodAll-        :: forall p g as. ()-        => (forall a. g a -> p @@ a)-        -> Prod [] g as-        -> All [] p @@ as-    prodAll f = go-      where-        go :: Prod [] g bs -> All [] p @@ bs-        go = \case-          RNil    -> WitAll $ \case {}-          x :& xs -> WitAll $ \case-            IZ   -> f x-            IS i -> runWitAll (go xs) i+  prodAll ::+    forall p g as.+    () =>+    (forall a. g a -> p @@ a) ->+    Prod [] g as ->+    All [] p @@ as+  prodAll f = go+    where+      go :: Prod [] g bs -> All [] p @@ bs+      go = \case+        RNil -> WitAll $ \case {}+        x :& xs -> WitAll $ \case+          IZ -> f x+          IS i -> runWitAll (go xs) i  instance Universe Maybe where-    idecideAny f = \case-      SNothing -> Disproved $ \case WitAny i _ -> case i of {}-      SJust x  -> case f IJust x of-        Proved p    -> Proved $ WitAny IJust p-        Disproved v -> Disproved $ \case-          WitAny IJust p -> v p-    idecideAll f = \case-      SNothing -> Proved $ WitAll $ \case {}-      SJust x  -> case f IJust x of-        Proved p    -> Proved $ WitAll $ \case IJust -> p-        Disproved v -> Disproved $ \a -> v $ runWitAll a IJust-    allProd f = \case-      SNothing -> \_ -> PNothing-      SJust x  -> \a -> PJust (f x (runWitAll a IJust))-    prodAll f = \case-      PNothing -> WitAll $ \case {}-      PJust x  -> WitAll $ \case IJust -> f x+  idecideAny f = \case+    SNothing -> Disproved $ \case WitAny i _ -> case i of {}+    SJust x -> case f IJust x of+      Proved p -> Proved $ WitAny IJust p+      Disproved v -> Disproved $ \case+        WitAny IJust p -> v p+  idecideAll f = \case+    SNothing -> Proved $ WitAll $ \case {}+    SJust x -> case f IJust x of+      Proved p -> Proved $ WitAll $ \case IJust -> p+      Disproved v -> Disproved $ \a -> v $ runWitAll a IJust+  allProd f = \case+    SNothing -> \_ -> PNothing+    SJust x -> \a -> PJust (f x (runWitAll a IJust))+  prodAll f = \case+    PNothing -> WitAll $ \case {}+    PJust x -> WitAll $ \case IJust -> f x  instance Universe (Either j) where-    idecideAny f = \case-      SLeft  _ -> Disproved $ \case WitAny i _ -> case i of {}-      SRight x -> case f IRight x of-        Proved p    -> Proved $ WitAny IRight p-        Disproved v -> Disproved $ \case-          WitAny IRight p -> v p-    idecideAll f = \case-      SLeft  _ -> Proved $ WitAll $ \case {}-      SRight x -> case f IRight x of-        Proved p    -> Proved $ WitAll $ \case IRight -> p-        Disproved v -> Disproved $ \a -> v $ runWitAll a IRight-    allProd f = \case-      SLeft  w -> \_ -> PLeft w-      SRight x -> \a -> PRight (f x (runWitAll a IRight))-    prodAll f = \case-      PLeft _  -> WitAll $ \case {}-      PRight x -> WitAll $ \case IRight -> f x+  idecideAny f = \case+    SLeft _ -> Disproved $ \case WitAny i _ -> case i of {}+    SRight x -> case f IRight x of+      Proved p -> Proved $ WitAny IRight p+      Disproved v -> Disproved $ \case+        WitAny IRight p -> v p+  idecideAll f = \case+    SLeft _ -> Proved $ WitAll $ \case {}+    SRight x -> case f IRight x of+      Proved p -> Proved $ WitAll $ \case IRight -> p+      Disproved v -> Disproved $ \a -> v $ runWitAll a IRight+  allProd f = \case+    SLeft w -> \_ -> PLeft w+    SRight x -> \a -> PRight (f x (runWitAll a IRight))+  prodAll f = \case+    PLeft _ -> WitAll $ \case {}+    PRight x -> WitAll $ \case IRight -> f x  instance Universe NonEmpty where-    idecideAny-        :: forall k (p :: k ~> Type) (as :: NonEmpty k). ()-        => (forall a. Elem NonEmpty as a -> Sing a -> Decision (p @@ a))-        -> Sing as-        -> Decision (Any NonEmpty p @@ as)-    idecideAny f (x NE.:%| xs) = case f NEHead x of-      Proved p    -> Proved $ WitAny NEHead p-      Disproved v -> case idecideAny @[] @_ @p (f . NETail) xs of-        Proved (WitAny i p) -> Proved $ WitAny (NETail i) p-        Disproved vs     -> Disproved $ \case-          WitAny i p -> case i of-            NEHead    -> v p-            NETail i' -> vs (WitAny i' p)+  idecideAny ::+    forall k (p :: k ~> Type) (as :: NonEmpty k).+    () =>+    (forall a. Elem NonEmpty as a -> Sing a -> Decision (p @@ a)) ->+    Sing as ->+    Decision (Any NonEmpty p @@ as)+  idecideAny f (x NE.:%| xs) = case f NEHead x of+    Proved p -> Proved $ WitAny NEHead p+    Disproved v -> case idecideAny @[] @_ @p (f . NETail) xs of+      Proved (WitAny i p) -> Proved $ WitAny (NETail i) p+      Disproved vs -> Disproved $ \case+        WitAny i p -> case i of+          NEHead -> v p+          NETail i' -> vs (WitAny i' p) -    idecideAll-        :: forall k (p :: k ~> Type) (as :: NonEmpty k). ()-        => (forall a. Elem NonEmpty as a -> Sing a -> Decision (p @@ a))-        -> Sing as-        -> Decision (All NonEmpty p @@ as)-    idecideAll f (x NE.:%| xs) = case f NEHead x of-      Proved p -> case idecideAll @[] @_ @p (f . NETail) xs of-        Proved ps -> Proved $ WitAll $ \case-          NEHead   -> p-          NETail i -> runWitAll ps i-        Disproved v -> Disproved $ \a -> v $ WitAll (runWitAll a . NETail)-      Disproved v -> Disproved $ \a -> v $ runWitAll a NEHead+  idecideAll ::+    forall k (p :: k ~> Type) (as :: NonEmpty k).+    () =>+    (forall a. Elem NonEmpty as a -> Sing a -> Decision (p @@ a)) ->+    Sing as ->+    Decision (All NonEmpty p @@ as)+  idecideAll f (x NE.:%| xs) = case f NEHead x of+    Proved p -> case idecideAll @[] @_ @p (f . NETail) xs of+      Proved ps -> Proved $ WitAll $ \case+        NEHead -> p+        NETail i -> runWitAll ps i+      Disproved v -> Disproved $ \a -> v $ WitAll (runWitAll a . NETail)+    Disproved v -> Disproved $ \a -> v $ runWitAll a NEHead -    allProd-        :: forall p g. ()-        => (forall a. Sing a -> p @@ a -> g a)-        -> All NonEmpty p --> TyPred (Prod NonEmpty g)-    allProd f (x NE.:%| xs) a =-          f x (runWitAll a NEHead)+  allProd ::+    forall p g.+    () =>+    (forall a. Sing a -> p @@ a -> g a) ->+    All NonEmpty p --> TyPred (Prod NonEmpty g)+  allProd f (x NE.:%| xs) a =+    f x (runWitAll a NEHead)       :&| allProd @[] @p f xs (WitAll (runWitAll a . NETail))-    prodAll-        :: forall p g as. ()-        => (forall a. g a -> p @@ a)-        -> Prod NonEmpty g as-        -> All NonEmpty p @@ as-    prodAll f (x :&| xs) = WitAll $ \case-        NEHead   -> f x-        NETail i -> runWitAll (prodAll @[] @p f xs) i+  prodAll ::+    forall p g as.+    () =>+    (forall a. g a -> p @@ a) ->+    Prod NonEmpty g as ->+    All NonEmpty p @@ as+  prodAll f (x :&| xs) = WitAll $ \case+    NEHead -> f x+    NETail i -> runWitAll (prodAll @[] @p f xs) i  instance Universe ((,) j) where-    idecideAny f (STuple2 _ x) = case f ISnd x of-      Proved p    -> Proved $ WitAny ISnd p-      Disproved v -> Disproved $ \case WitAny ISnd p -> v p-    idecideAll f (STuple2 _ x) = case f ISnd x of-      Proved p    -> Proved $ WitAll $ \case ISnd -> p-      Disproved v -> Disproved $ \a -> v $ runWitAll a ISnd-    allProd f (STuple2 w x) a = PTup w $ f x (runWitAll a ISnd)-    prodAll f (PTup _ x) = WitAll $ \case ISnd -> f x+  idecideAny f (STuple2 _ x) = case f ISnd x of+    Proved p -> Proved $ WitAny ISnd p+    Disproved v -> Disproved $ \case WitAny ISnd p -> v p+  idecideAll f (STuple2 _ x) = case f ISnd x of+    Proved p -> Proved $ WitAll $ \case ISnd -> p+    Disproved v -> Disproved $ \a -> v $ runWitAll a ISnd+  allProd f (STuple2 w x) a = PTup w $ f x (runWitAll a ISnd)+  prodAll f (PTup _ x) = WitAll $ \case ISnd -> f x  -- | The single-pointed universe. instance Universe Identity where-    idecideAny f (SIdentity x) =-        mapDecision (WitAny IId)-                    (\case WitAny IId p -> p)+  idecideAny f (SIdentity x) =+    mapDecision+      (WitAny IId)+      (\case WitAny IId p -> p)       $ f IId x-    idecideAll f (SIdentity x) =-        mapDecision (\p -> WitAll $ \case IId -> p)-                    (\y -> runWitAll y IId)+  idecideAll f (SIdentity x) =+    mapDecision+      (\p -> WitAll $ \case IId -> p)+      (\y -> runWitAll y IId)       $ f IId x-    allProd f (SIdentity x) a = PIdentity $ f x (runWitAll a IId)-    prodAll f (PIdentity x) = WitAll $ \case IId -> f x+  allProd f (SIdentity x) a = PIdentity $ f x (runWitAll a IId)+  prodAll f (PIdentity x) = WitAll $ \case IId -> f x
src/Data/Type/Universe/Subset.hs view
@@ -1,10 +1,11 @@ {-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications    #-}-{-# LANGUAGE TypeFamilies        #-}-{-# LANGUAGE TypeInType          #-}-{-# LANGUAGE TypeOperators       #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}  -- | -- Module      : Data.Type.Universe.Subset@@ -16,72 +17,88 @@ -- Portability : non-portable -- -- Represent a decidable subset of a type-level collection.--- module Data.Type.Universe.Subset (   -- * Subset-    Subset, WitSubset(..)-  , makeSubset+  Subset,+  WitSubset (..),+  makeSubset,+   -- ** Subset manipulation-  , intersection, union, symDiff, mergeSubset, imergeSubset-  , mapSubset, imapSubset+  intersection,+  union,+  symDiff,+  mergeSubset,+  imergeSubset,+  mapSubset,+  imapSubset,+   -- ** Subset extraction-  , subsetToList+  subsetToList,+   -- ** Subset tests-  , subsetToAny, subsetToAll, subsetToNone+  subsetToAny,+  subsetToAll,+  subsetToNone,+   -- ** Subset construction-  , emptySubset, fullSubset-  ) where+  emptySubset,+  fullSubset,+) where -import           Control.Applicative-import           Data.Kind-import           Data.Monoid                        (Alt(..))-import           Data.Singletons-import           Data.Singletons.Decide-import           Data.Type.Functor.Product-import           Data.Type.Predicate-import           Data.Type.Predicate.Logic-import           Data.Type.Predicate.Quantification-import           Data.Type.Universe+import Control.Applicative+import Data.Kind+import Data.Monoid (Alt (..))+import Data.Singletons+import Data.Singletons.Decide+import Data.Type.Functor.Product+import Data.Type.Predicate+import Data.Type.Predicate.Logic+import Data.Type.Predicate.Quantification+import Data.Type.Universe  -- | A @'WitSubset' f p @@ as@ describes a /decidable/ subset of type-level -- collection @as@. newtype WitSubset f p (as :: f k) = WitSubset-    { runWitSubset :: forall a. Elem f as a -> Decision (p @@ a)-    }+  { runWitSubset :: forall a. Elem f as a -> Decision (p @@ a)+  }  -- | A @'Subset' f p@ is a predicate that some decidable subset of an input -- @as@ is true. data Subset f :: (k ~> Type) -> (f k ~> Type)+ type instance Apply (Subset f p) as = WitSubset f p as  instance (Universe f, Decidable p) => Decidable (Subset f p) instance (Universe f, Decidable p) => Provable (Subset f p) where-    prove = makeSubset @f @_ @p (\_ -> decide @p)+  prove = makeSubset @f @_ @p (\_ -> decide @p)  -- | Create a 'Subset' from a predicate.-makeSubset-    :: forall f k p (as :: f k). Universe f-    => (forall a. Elem f as a -> Sing a -> Decision (p @@ a))-    -> Sing as-    -> Subset f p @@ as+makeSubset ::+  forall f k p (as :: f k).+  Universe f =>+  (forall a. Elem f as a -> Sing a -> Decision (p @@ a)) ->+  Sing as ->+  Subset f p @@ as makeSubset f xs = WitSubset $ \i -> f i (indexSing i xs)  -- | Turn a 'Subset' into a list (or any 'Alternative') of satisfied -- predicates. -- -- List is meant to include no duplicates.-subsetToList-    :: forall f p t. (Universe f, Alternative t)-    => (Subset f p --># Any f p) t+subsetToList ::+  forall f p t.+  (Universe f, Alternative t) =>+  (Subset f p --># Any f p) t subsetToList xs s = getAlt $ (`ifoldMapSing` xs) $ \i _ -> Alt $ case runWitSubset s i of-    Proved p    -> pure $ WitAny i p-    Disproved _ -> empty+  Proved p -> pure $ WitAny i p+  Disproved _ -> empty  -- | Restrict a 'Subset' to a single (arbitrary) member, or fail if none -- exists.-subsetToAny-    :: forall f p. Universe f-    => Subset f p -?> Any f p+subsetToAny ::+  forall f p.+  Universe f =>+  Subset f p -?> Any f p subsetToAny xs s = idecideAny (\i _ -> runWitSubset s i) xs  -- | Construct an empty subset.@@ -97,67 +114,75 @@ subsetToNone xs s = idecideNone (\i _ -> runWitSubset s i) xs  -- | Combine two subsets based on a decision function-imergeSubset-    :: forall f k p q r (as :: f k). ()-    => (forall a. Elem f as a -> Decision (p @@ a) -> Decision (q @@ a) -> Decision (r @@ a))-    -> Subset f p @@ as-    -> Subset f q @@ as-    -> Subset f r @@ as+imergeSubset ::+  forall f k p q r (as :: f k).+  () =>+  (forall a. Elem f as a -> Decision (p @@ a) -> Decision (q @@ a) -> Decision (r @@ a)) ->+  Subset f p @@ as ->+  Subset f q @@ as ->+  Subset f r @@ as imergeSubset f ps qs = WitSubset $ \i ->-    f i (runWitSubset ps i) (runWitSubset qs i)+  f i (runWitSubset ps i) (runWitSubset qs i)  -- | Combine two subsets based on a decision function-mergeSubset-    :: forall f k p q r (as :: f k). ()-    => (forall a. Decision (p @@ a) -> Decision (q @@ a) -> Decision (r @@ a))-    -> Subset f p @@ as-    -> Subset f q @@ as-    -> Subset f r @@ as+mergeSubset ::+  forall f k p q r (as :: f k).+  () =>+  (forall a. Decision (p @@ a) -> Decision (q @@ a) -> Decision (r @@ a)) ->+  Subset f p @@ as ->+  Subset f q @@ as ->+  Subset f r @@ as mergeSubset f = imergeSubset (\(_ :: Elem f as a) p -> f @a p)  -- | Subset intersection-intersection-    :: forall f p q. ()-    => ((Subset f p &&& Subset f q) --> Subset f (p &&& q))+intersection ::+  forall f p q.+  () =>+  ((Subset f p &&& Subset f q) --> Subset f (p &&& q)) intersection _ = uncurry $ imergeSubset $ \(_ :: Elem f as a) -> decideAnd @p @q @a  -- | Subset union (left-biased)-union-    :: forall f p q. ()-    => ((Subset f p &&& Subset f q) --> Subset f (p ||| q))+union ::+  forall f p q.+  () =>+  ((Subset f p &&& Subset f q) --> Subset f (p ||| q)) union _ = uncurry $ imergeSubset $ \(_ :: Elem f as a) -> decideOr @p @q @a  -- | Symmetric subset difference-symDiff-    :: forall f p q. ()-    => ((Subset f p &&& Subset f q) --> Subset f (p ^^^ q))+symDiff ::+  forall f p q.+  () =>+  ((Subset f p &&& Subset f q) --> Subset f (p ^^^ q)) symDiff _ = uncurry $ imergeSubset $ \(_ :: Elem f as a) -> decideXor @p @q @a  -- | Test if a subset is equal to the entire original collection-subsetToAll-    :: forall f p. Universe f-    => Subset f p -?> All f p+subsetToAll ::+  forall f p.+  Universe f =>+  Subset f p -?> All f p subsetToAll xs s = idecideAll (\i _ -> runWitSubset s i) xs  -- | 'mapSubset', but providing an 'Elem'.-imapSubset-    :: (forall a. Elem f as a -> p @@ a -> q @@ a)-    -> (forall a. Elem f as a -> q @@ a -> p @@ a)-    -> Subset f p @@ as-    -> Subset f q @@ as+imapSubset ::+  (forall a. Elem f as a -> p @@ a -> q @@ a) ->+  (forall a. Elem f as a -> q @@ a -> p @@ a) ->+  Subset f p @@ as ->+  Subset f q @@ as imapSubset f g s = WitSubset $ \i ->-    mapDecision (f i) (g i) (runWitSubset s i)+  mapDecision (f i) (g i) (runWitSubset s i)  -- | Map a bidirectional implication over a subset described by that -- implication. -- -- Implication needs to be bidirectional, or otherwise we can't produce -- a /decidable/ subset as a result.-mapSubset-    :: Universe f-    => (p --> q)-    -> (q --> p)-    -> (Subset f p --> Subset f q)-mapSubset f g xs = withSingI xs $-    imapSubset (\i -> f (indexSing i xs))-               (\i -> g (indexSing i xs))+mapSubset ::+  Universe f =>+  (p --> q) ->+  (q --> p) ->+  (Subset f p --> Subset f q)+mapSubset f g xs =+  withSingI xs $+    imapSubset+      (\i -> f (indexSing i xs))+      (\i -> g (indexSing i xs))