packages feed

equational-reasoning 0.3.0.0 → 0.4.0.0

raw patch · 7 files changed

+431/−26 lines, 7 filesdep +containersdep +th-desugardep ~singletonsPVP ok

version bump matches the API change (PVP)

Dependencies added: containers, th-desugar

Dependency ranges changed: singletons

API changes (from Hackage documentation)

+ Proof.Propositional: [Witness] :: IsTrue True
+ Proof.Propositional: class Empty a where eliminate = geliminate . from
+ Proof.Propositional: class Inhabited a where trivial = to gtrivial
+ Proof.Propositional: data IsTrue (b :: Bool)
+ Proof.Propositional: eliminate :: (Empty a, Generic a, GEmpty (Rep a)) => a -> x
+ Proof.Propositional: instance (Proof.Propositional.Inhabited.Inhabited a, Proof.Propositional.Empty.Empty b) => Proof.Propositional.Empty.Empty (a -> b)
+ Proof.Propositional: instance Data.Data.Data (Proof.Propositional.IsTrue 'GHC.Types.True)
+ Proof.Propositional: instance GHC.Classes.Eq (Proof.Propositional.IsTrue b)
+ Proof.Propositional: instance GHC.Classes.Ord (Proof.Propositional.IsTrue b)
+ Proof.Propositional: instance GHC.Read.Read (Proof.Propositional.IsTrue 'GHC.Types.True)
+ Proof.Propositional: instance GHC.Show.Show (Proof.Propositional.IsTrue b)
+ Proof.Propositional: instance Proof.Propositional.Empty.Empty (() Data.Type.Equality.:~: GHC.Types.Int)
+ Proof.Propositional: instance Proof.Propositional.Empty.Empty (0 Data.Type.Equality.:~: 1)
+ Proof.Propositional: instance Proof.Propositional.Empty.Empty (Proof.Propositional.IsTrue 'GHC.Types.False)
+ Proof.Propositional: instance Proof.Propositional.Inhabited.Inhabited (GHC.Base.Maybe a0)
+ Proof.Propositional: instance Proof.Propositional.Inhabited.Inhabited (GHC.Real.Ratio GHC.Integer.Type.Integer)
+ Proof.Propositional: instance Proof.Propositional.Inhabited.Inhabited (Proof.Propositional.IsTrue 'GHC.Types.True)
+ Proof.Propositional: instance Proof.Propositional.Inhabited.Inhabited GHC.Integer.Type.Integer
+ Proof.Propositional: instance Proof.Propositional.Inhabited.Inhabited GHC.Types.Bool
+ Proof.Propositional: instance Proof.Propositional.Inhabited.Inhabited GHC.Types.Char
+ Proof.Propositional: instance Proof.Propositional.Inhabited.Inhabited GHC.Types.Double
+ Proof.Propositional: instance Proof.Propositional.Inhabited.Inhabited GHC.Types.Float
+ Proof.Propositional: instance Proof.Propositional.Inhabited.Inhabited GHC.Types.Int
+ Proof.Propositional: instance Proof.Propositional.Inhabited.Inhabited GHC.Types.Ordering
+ Proof.Propositional: instance Proof.Propositional.Inhabited.Inhabited GHC.Types.Word
+ Proof.Propositional: instance Proof.Propositional.Inhabited.Inhabited [a0]
+ Proof.Propositional: instance forall k (n0 :: k). Proof.Propositional.Inhabited.Inhabited (n0 Data.Type.Equality.:~: n0)
+ Proof.Propositional: prove :: TypeQ -> DecsQ
+ Proof.Propositional: refute :: TypeQ -> DecsQ
+ Proof.Propositional: trivial :: (Inhabited a, Generic a, GInhabited (Rep a)) => a
+ Proof.Propositional: withEmpty :: forall a b. (a -> Void) -> (Empty a => b) -> b
+ Proof.Propositional: withEmpty' :: forall a b. (forall c. a -> c) -> (Empty a => b) -> b
+ Proof.Propositional: withInhabited :: forall a b. a -> (Inhabited a => b) -> b
+ Proof.Propositional.Empty: class Empty a where eliminate = geliminate . from
+ Proof.Propositional.Empty: eliminate :: (Empty a, Generic a, GEmpty (Rep a)) => a -> x
+ Proof.Propositional.Empty: instance (Proof.Propositional.Empty.Empty a, Proof.Propositional.Empty.Empty b) => Proof.Propositional.Empty.Empty (Data.Either.Either a b)
+ Proof.Propositional.Empty: instance (Proof.Propositional.Empty.GEmpty f, Proof.Propositional.Empty.GEmpty g) => Proof.Propositional.Empty.GEmpty (f GHC.Generics.:+: g)
+ Proof.Propositional.Empty: instance Proof.Propositional.Empty.Empty Data.Void.Void
+ Proof.Propositional.Empty: instance Proof.Propositional.Empty.Empty c => Proof.Propositional.Empty.GEmpty (GHC.Generics.K1 i c)
+ Proof.Propositional.Empty: instance Proof.Propositional.Empty.GEmpty GHC.Generics.V1
+ Proof.Propositional.Empty: instance Proof.Propositional.Empty.GEmpty f => Proof.Propositional.Empty.GEmpty (GHC.Generics.M1 i t f)
+ Proof.Propositional.Empty: withEmpty :: forall a b. (a -> Void) -> (Empty a => b) -> b
+ Proof.Propositional.Empty: withEmpty' :: forall a b. (forall c. a -> c) -> (Empty a => b) -> b
+ Proof.Propositional.Inhabited: class Inhabited a where trivial = to gtrivial
+ Proof.Propositional.Inhabited: instance (Proof.Propositional.Inhabited.GInhabited f, Proof.Propositional.Inhabited.GInhabited g) => Proof.Propositional.Inhabited.GInhabited (f GHC.Generics.:*: g)
+ Proof.Propositional.Inhabited: instance (Proof.Propositional.Inhabited.Inhabited a, Proof.Propositional.Inhabited.Inhabited b) => Proof.Propositional.Inhabited.Inhabited (a, b)
+ Proof.Propositional.Inhabited: instance (Proof.Propositional.Inhabited.Inhabited a, Proof.Propositional.Inhabited.Inhabited b, Proof.Propositional.Inhabited.Inhabited c) => Proof.Propositional.Inhabited.Inhabited (a, b, c)
+ Proof.Propositional.Inhabited: instance (Proof.Propositional.Inhabited.Inhabited a, Proof.Propositional.Inhabited.Inhabited b, Proof.Propositional.Inhabited.Inhabited c, Proof.Propositional.Inhabited.Inhabited d) => Proof.Propositional.Inhabited.Inhabited (a, b, c, d)
+ Proof.Propositional.Inhabited: instance Proof.Propositional.Inhabited.GInhabited GHC.Generics.U1
+ Proof.Propositional.Inhabited: instance Proof.Propositional.Inhabited.GInhabited f => Proof.Propositional.Inhabited.GInhabited (GHC.Generics.M1 i t f)
+ Proof.Propositional.Inhabited: instance Proof.Propositional.Inhabited.Inhabited ()
+ Proof.Propositional.Inhabited: instance Proof.Propositional.Inhabited.Inhabited b => Proof.Propositional.Inhabited.Inhabited (a -> b)
+ Proof.Propositional.Inhabited: instance Proof.Propositional.Inhabited.Inhabited c => Proof.Propositional.Inhabited.GInhabited (GHC.Generics.K1 i c)
+ Proof.Propositional.Inhabited: trivial :: (Inhabited a, Generic a, GInhabited (Rep a)) => a
+ Proof.Propositional.Inhabited: withInhabited :: forall a b. a -> (Inhabited a => b) -> b
- Proof.Equational: (=~=) :: Preorder r => r x y -> Sing y -> r x y
+ Proof.Equational: (=~=) :: r x y -> Sing y -> r x y

Files

Proof/Equational.hs view
@@ -112,7 +112,7 @@ (===) = (=<=) {-# SPECIALISE INLINE[1] (===) :: x :~: y -> Reason (:~:) y z -> x :~: z #-} -(=~=) :: Preorder r => r x y -> Sing y -> r x y+(=~=) :: r x y -> Sing y -> r x y eq =~= _ = eq  start :: Preorder eq => Sing a -> eq a a@@ -182,15 +182,12 @@ instance KnownTypeList ts => KnownTypeList (t ': ts) where   viewHVec' = HConsView Proxy viewHVec' -viewHVec :: KnownTypeList ts => HVec ts -> HVecView ts-viewHVec _ = viewHVec'- newtype Magic (xs :: [*]) a = Magic { _viewHVec' :: KnownTypeList xs => a }  withKnownTypeList :: forall a xs. HVecView xs -> (KnownTypeList xs => a) -> a withKnownTypeList xs f = (unsafeCoerce (Magic f :: Magic xs a) :: HVecView xs -> a) xs -apply' :: (KnownTypeList ts) => HVecView ts -> (HVec ts -> c) -> ts :~> c+apply' :: HVecView ts -> (HVec ts -> c) -> ts :~> c apply' HNilView f = f HNil apply' (HConsView Proxy ts) f = \a -> withKnownTypeList ts $   apply' ts (\ts' -> f $ a :- ts')@@ -206,5 +203,5 @@   type Args c :: [*]   fromBool :: Predicate c ~ 'True => HVec (Args c) -> c -fromBool' :: forall proxy c. (KnownTypeList (Args c), FromBool c , Predicate c ~ True) => proxy c -> Args c :~> c+fromBool' :: forall proxy c. (KnownTypeList (Args c), FromBool c , Predicate c ~ 'True) => proxy c -> Args c :~> c fromBool' pxyc = applyNAry' (Proxy :: Proxy (Args c)) pxyc fromBool
Proof/Internal/THCompat.hs view
@@ -1,12 +1,12 @@ {-# LANGUAGE CPP, PatternSynonyms, TemplateHaskell, ViewPatterns #-} module Proof.Internal.THCompat where import Language.Haskell.TH-import Language.Haskell.TH.Syntax+ import GHC.Exts (Constraint)  mkDataD :: Cxt -> Name -> [TyVarBndr] -> [Con] -> [Name] -> Dec-mkDataD cxt name tvbndrs cons names =-  DataD cxt name tvbndrs+mkDataD ctx name tvbndrs cons names =+  DataD ctx name tvbndrs #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 800         Nothing cons (map ConT names) #else@@ -29,16 +29,16 @@ typeName ConstraintT = ''Constraint typeName _ = error "No names!" -pattern DataDCompat cxt name tvbndrs cons names <--  DataD cxt name tvbndrs+pattern DataDCompat ctx name tvbndrs cons names <-+  DataD ctx name tvbndrs #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 800         _ cons (map typeName -> names) #else         cons names #endif -pattern NewtypeDCompat cxt name tvbndrs con names <--  NewtypeD cxt name tvbndrs+pattern NewtypeDCompat ctx name tvbndrs con names <-+  NewtypeD ctx name tvbndrs #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 800         _ con (map typeName -> names) #else
Proof/Propositional.hs view
@@ -1,10 +1,26 @@-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE DataKinds, DeriveDataTypeable, EmptyCase, ExplicitForAll     #-}+{-# LANGUAGE ExplicitNamespaces, FlexibleInstances, GADTs, KindSignatures #-}+{-# LANGUAGE LambdaCase, PolyKinds, StandaloneDeriving, TemplateHaskell   #-}+{-# LANGUAGE TypeOperators                                                #-}+{-# OPTIONS_GHC -fno-warn-orphans #-} -- | Provides type synonyms for logical connectives.-module Proof.Propositional ( type (/\), type (\/), Not, exfalso, orIntroL-                           , orIntroR, orElim, andIntro, andElimL-                           , andElimR, orAssocL, orAssocR-                           , andAssocL, andAssocR-                           ) where+module Proof.Propositional+       ( type (/\), type (\/), Not, exfalso, orIntroL+       , orIntroR, orElim, andIntro, andElimL+       , andElimR, orAssocL, orAssocR+       , andAssocL, andAssocR, IsTrue(..)+       , Empty(..), withEmpty, withEmpty'+       , refute+       , Inhabited (..), withInhabited+       , prove+       ) where+import Proof.Propositional.Empty+import Proof.Propositional.Inhabited+import Proof.Propositional.TH++import Data.Data          (Data)+import Data.Type.Equality ((:~:))+import Data.Typeable      (Typeable) import Data.Void  type a /\ b = (a, b)@@ -50,3 +66,39 @@ orAssocR (Left (Left a))  = Left a orAssocR (Left (Right b)) = Right (Left b) orAssocR (Right c)        = Right (Right c)+++-- | Utility type to convert type-level (@'Bool'@-valued) predicate function+--   into concrete witness data-type.+data IsTrue (b :: Bool) where+  Witness :: IsTrue 'True++deriving instance Show (IsTrue b)+deriving instance Eq   (IsTrue b)+deriving instance Ord  (IsTrue b)+deriving instance Read (IsTrue 'True)+deriving instance Typeable IsTrue+deriving instance Data (IsTrue 'True)++instance {-# OVERLAPPABLE #-} (Inhabited a, Empty b) => Empty (a -> b) where+  eliminate f = eliminate (f trivial)++refute [t| 0 :~: 1 |]+refute [t| () :~: Int |]++prove [t| Bool |]+prove [t| Int |]+prove [t| Integer |]+prove [t| Word |]+prove [t| Double |]+prove [t| Float |]+prove [t| Char |]+prove [t| Ordering |]+prove [t| forall a. [a] |]+prove [t| Rational |]+prove [t| forall a. Maybe a |]+prove [t| forall n. n :~: n |]+prove [t| IsTrue 'True |]++instance Empty (IsTrue 'False) where+  eliminate = \ case {}
+ Proof/Propositional/Empty.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE RankNTypes, ScopedTypeVariables #-}+{-# LANGUAGE DataKinds, DefaultSignatures, DeriveAnyClass, EmptyCase #-}+{-# LANGUAGE ExplicitNamespaces, FlexibleContexts, FlexibleInstances #-}+{-# LANGUAGE GADTs, KindSignatures, LambdaCase, PolyKinds            #-}+{-# LANGUAGE StandaloneDeriving, TupleSections, TypeOperators        #-}+module Proof.Propositional.Empty (Empty(..), withEmpty, withEmpty') where+import Data.Void          (Void, absurd)+import GHC.Generics+import Unsafe.Coerce      (unsafeCoerce)++-- | Type-class for types without inhabitants, dual to @'Proof.Propositional.Inhabited'@.+--   Current GHC doesn't provide selective-instance,+--   hence we don't @'Empty'@ provide instances+--   for product types in a generic deriving (DeriveAnyClass).+-- +--   To derive an instance for each concrete types,+--   use @'Proof.Propositional.refute'@.+--+--   Since 0.4.0.0.+class Empty a where+  eliminate :: a -> x++  default eliminate :: (Generic a, GEmpty (Rep a)) => a -> x+  eliminate = geliminate . from++class GEmpty f where+  geliminate :: f a -> x++instance GEmpty f => GEmpty (M1 i t f) where+  geliminate (M1 a) = geliminate a++instance (GEmpty f, GEmpty g) => GEmpty (f :+: g) where+  geliminate (L1 a) = geliminate a+  geliminate (R1 b) = geliminate b++instance Empty c => GEmpty (K1 i c) where+  geliminate (K1 a) = eliminate a++instance GEmpty V1 where+  geliminate = \ case {}++deriving instance (Empty a, Empty b) => Empty (Either a b)+deriving instance Empty Void++newtype MagicEmpty e a = MagicEmpty (Empty e => a)++-- | Giving falsity witness by proving @'Void'@ from @a@.+--   See also 'withEmpty''.+--+--   Since 0.4.0.0+withEmpty :: forall a b. (a -> Void) -> (Empty a => b) -> b+withEmpty neg k = unsafeCoerce (MagicEmpty k :: MagicEmpty a b) (absurd . neg)++-- | Giving falsity witness by showing @a@ entails everything.+--   See also 'withEmpty'.+--+--   Since 0.4.0.0+withEmpty' :: forall a b. (forall c. a -> c) -> (Empty a => b) -> b+withEmpty' neg k = unsafeCoerce (MagicEmpty k :: MagicEmpty a b) neg
+ Proof/Propositional/Inhabited.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE DataKinds, DefaultSignatures, DeriveAnyClass, EmptyCase  #-}+{-# LANGUAGE ExplicitNamespaces, FlexibleContexts, FlexibleInstances  #-}+{-# LANGUAGE GADTs, KindSignatures, LambdaCase, PolyKinds, RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables, StandaloneDeriving, TupleSections   #-}+{-# LANGUAGE TypeOperators                                            #-}+module Proof.Propositional.Inhabited (Inhabited(..), withInhabited) where+import GHC.Generics+import Unsafe.Coerce (unsafeCoerce)++-- | Types with at least one inhabitant, dual to @'Proof.Propositional.Empty'@.+-- | Current GHC doesn't provide selective-instance,+--   hence we don't @'Empty'@ provide instances+--   for sum types in a generic deriving (DeriveAnyClass).+--+--   To derive an instance for each concrete types,+--   use @'Proof.Propositional.prove'@.+--+--   Since 0.4.0.0.+class Inhabited a where+  trivial :: a++  default trivial :: (Generic a, GInhabited (Rep a)) => a+  trivial = to gtrivial++class GInhabited f where+  gtrivial :: f a++instance GInhabited f => GInhabited (M1 i t f) where+  gtrivial = M1 gtrivial++instance (GInhabited f, GInhabited g) => GInhabited (f :*: g) where+  gtrivial = gtrivial :*: gtrivial++instance Inhabited c => GInhabited (K1 i c) where+  gtrivial = K1 trivial++instance GInhabited U1 where+  gtrivial = U1++deriving instance Inhabited ()+deriving instance (Inhabited a, Inhabited b) => Inhabited (a, b)+deriving instance (Inhabited a, Inhabited b, Inhabited c) => Inhabited (a, b, c)+deriving instance (Inhabited a, Inhabited b, Inhabited c, Inhabited d) => Inhabited (a, b, c, d)++instance Inhabited b => Inhabited (a -> b) where+  trivial = const trivial++newtype MagicInhabited a b = MagicInhabited (Inhabited a => b)++withInhabited :: forall a b. a -> (Inhabited a => b) -> b+withInhabited wit k = unsafeCoerce (MagicInhabited k :: MagicInhabited a b) wit
+ Proof/Propositional/TH.hs view
@@ -0,0 +1,243 @@+{-# LANGUAGE ExplicitNamespaces, MultiWayIf, PatternGuards, TemplateHaskell #-}+{-# LANGUAGE TupleSections                                                  #-}+module Proof.Propositional.TH where+import Proof.Propositional.Empty+import Proof.Propositional.Inhabited++import           Control.Arrow               (Kleisli (..), second)+import           Control.Monad               (forM, zipWithM)+import           Data.Foldable               (asum)+import           Data.Map                    (Map)+import qualified Data.Map                    as M+import           Data.Maybe                  (fromJust)+import           Data.Monoid                 ((<>))+import           Data.Type.Equality          ((:~:) (..))+import           Language.Haskell.TH         (DecsQ, Lit (CharL, IntegerL))+import           Language.Haskell.TH         (Name, Q, TypeQ, isInstance)+import           Language.Haskell.TH         (newName, ppr)+import           Language.Haskell.TH.Desugar (DClause (..), DCon (..))+import           Language.Haskell.TH.Desugar (DConFields (..), DCxt, DDec (..))+import           Language.Haskell.TH.Desugar (DExp (..), DInfo (..))+import           Language.Haskell.TH.Desugar (DLetDec (DFunD))+import           Language.Haskell.TH.Desugar (DPat (DConPa, DVarPa), DPred (..))+import           Language.Haskell.TH.Desugar (DTyVarBndr (..), DType (..))+import           Language.Haskell.TH.Desugar (Overlap (Overlapping), desugar)+import           Language.Haskell.TH.Desugar (dsReify, expandType, substTy)+import           Language.Haskell.TH.Desugar (sweeten)+++-- | Macro to automatically derive @'Empty'@ instance for+--   concrete (variable-free) types which may contain products.+refute :: TypeQ -> DecsQ+refute tps = do+  tp <- expandType =<< desugar =<< tps+  let Just (_, tyName, args) = splitType tp+      mkInst dxt cls = return $ sweeten+                       [DInstanceD (Just Overlapping) dxt+                        (DAppT (DConT ''Empty) (foldl DAppT (DConT tyName) args))+                        [DLetDec $ DFunD 'eliminate cls]+                         ]+  if tyName == ''(:~:)+    then do+      let [l, r] = args+      v    <- newName "_v"+      dist <- compareType l r+      case dist of+        NonEqual    -> mkInst [] [DClause [] $ DLamE [v] (DCaseE (DVarE v) []) ]+        Equal       -> fail $ "Equal: " ++ show (ppr $ sweeten l) ++ " ~ " ++ show (ppr $ sweeten r)+        Undecidable -> fail $ "No enough info to check non-equality: " +++                         show (ppr $ sweeten l) ++ " ~ " ++ show (ppr $ sweeten r)+    else do+      (dxt, cons) <- resolveSubsts args . fromJust =<< dsReify tyName+      Just cls <- sequence <$> mapM buildRefuteClause cons+      mkInst dxt cls++-- | Macro to automatically derive @'Inhabited'@ instance for+--   concrete (variable-free) types which may contain sums.+prove :: TypeQ -> DecsQ+prove tps = do+  tp <- expandType =<< desugar =<< tps+  let Just (_, tyName, args) = splitType tp+      mkInst dxt cls = return $ sweeten+                       [DInstanceD (Just Overlapping) dxt+                        (DAppT (DConT ''Inhabited) (foldl DAppT (DConT tyName) args))+                        [DLetDec $ DFunD 'trivial cls]+                         ]+  isNum <- isInstance ''Num [sweeten tp]++  if | isNum -> mkInst [] [DClause [] $ DLitE $ IntegerL 0 ]+     | tyName == ''Char  -> mkInst [] [DClause [] $ DLitE $ CharL '\NUL']+     | tyName == ''(:~:) -> do+        let [l, r] = args+        dist <- compareType l r+        case dist of+          NonEqual    -> fail $ "Equal: " ++ show (ppr $ sweeten l) ++ " ~ " ++ show (ppr $ sweeten r)+          Equal       -> mkInst [] [DClause [] $ DConE 'Refl ]+          Undecidable -> fail $ "No enough info to check non-equality: " +++                           show (ppr $ sweeten l) ++ " ~ " ++ show (ppr $ sweeten r)+     | otherwise -> do+        (dxt, cons) <- resolveSubsts args . fromJust =<< dsReify tyName+        Just cls <- asum <$> mapM buildProveClause cons+        mkInst dxt [cls]++buildClause :: Name -> (DType -> Q b) -> (DType -> b -> DExp)+            -> (Name -> [Maybe DExp] -> Maybe DExp) -> (Name -> [b] -> [DPat])+            -> DCon -> Q (Maybe DClause)+buildClause clsName genPlaceHolder buildFactor flattenExps toPats (DCon _ _ cName flds _) = do+  let tys = fieldsVars flds+  varDic <- mapM genPlaceHolder tys+  fmap (DClause $ toPats cName varDic) . flattenExps cName <$> zipWithM tryProc tys varDic+  where+    tryProc ty name = do+      isEmpty <- isInstance clsName . (:[]) $ sweeten ty+      return $ if isEmpty+        then Just $ buildFactor ty name+        else Nothing++buildRefuteClause :: DCon -> Q (Maybe DClause)+buildRefuteClause =+  buildClause+    ''Empty (const $ newName "_x")+    (const $ (DVarE 'eliminate `DAppE`) . DVarE) (const asum)+    (\cName ps -> [DConPa cName $ map DVarPa ps])++buildProveClause :: DCon -> Q (Maybe DClause)+buildProveClause  =+  buildClause+    ''Inhabited (const $ return ())+    (const $ const $ DVarE 'trivial)+    (\ con args -> foldl DAppE (DConE con) <$> sequence args )+    (const $ const [])++fieldsVars :: DConFields -> [DType]+fieldsVars (DNormalC fs) = map snd fs+fieldsVars (DRecC fs) = map (\(_,_,c) -> c) fs++resolveSubsts :: [DType] -> DInfo -> Q (DCxt, [DCon])+resolveSubsts args info = do+  case info of+    (DTyConI (DDataD _ cxt _ tvbs dcons _) _) -> do+      let dic = M.fromList $ zip (map dtvbToName tvbs) args+      (cxt , ) <$> mapM (substDCon dic) dcons+    -- (DTyConI (DOpenTypeFamilyD n) _) ->  return []+    -- (DTyConI (DClosedTypeFamilyD _ ddec2) minst) ->  return []+    -- (DTyConI (DDataFamilyD _ ddec2) minst) ->  return []+    -- (DTyConI (DDataInstD _ ddec2 ddec3 ddec4 ddec5 ddec6) minst) ->  return []+    (DTyConI _ _) -> fail "Not supported data ty"+    _ -> fail "Please pass data-type"++type SubstDic = Map Name DType++substDCon :: SubstDic -> DCon -> Q DCon+substDCon dic (DCon forall'd cxt conName fields mPhantom) =+  DCon forall'd cxt conName+    <$> substFields dic fields+    <*> mapM (substTy dic) mPhantom++substFields :: SubstDic -> DConFields -> Q DConFields+substFields subst (DNormalC fs) = DNormalC <$> mapM (runKleisli $ second $ Kleisli $ substTy subst) fs+substFields subst (DRecC fs) =+  DRecC <$> forM fs (\(a,b,c) -> (a, b ,) <$> substTy subst c)++dtvbToName :: DTyVarBndr -> Name+dtvbToName (DPlainTV n) = n+dtvbToName (DKindedTV n _) = n++splitType :: DType -> Maybe ([Name], Name, [DType])+splitType (DForallT vs _ t) = (\(a,b,c) -> (map dtvbToName vs ++ a, b, c)) <$> splitType t+splitType (DAppT t1 t2) = (\(a,b,c) -> (a, b, c ++ [t2])) <$> splitType t1+splitType (DSigT t _) = splitType t+splitType (DVarT _) = Nothing+splitType (DConT n) = Just ([], n, [])+splitType DArrowT = Just ([], ''(->), [])+splitType (DLitT _) = Nothing+splitType DWildCardT = Nothing+splitType DStarT = Nothing++data EqlJudge = NonEqual | Undecidable | Equal+              deriving (Read, Show, Eq, Ord)++instance Monoid EqlJudge where+  NonEqual    `mappend` _        = NonEqual+  Undecidable `mappend` NonEqual = NonEqual+  Undecidable `mappend` _        = Undecidable+  Equal       `mappend` m        = m++  mempty = Equal++compareType :: DType -> DType -> Q EqlJudge+compareType t0 s0 = do+  t <- expandType t0+  s <- expandType s0+  compareType' t s++compareType' :: DType -> DType -> Q EqlJudge+compareType' (DSigT t1 t2) (DSigT s1 s2)+  = (<>) <$> compareType' t1 s1 <*> compareType' t2 s2+compareType' (DSigT t _) s+  = compareType' t s+compareType' t (DSigT s _)+  = compareType' t s+compareType' (DVarT t) (DVarT s)+  | t == s    = return Equal+  | otherwise = return Undecidable+compareType' (DVarT _) _ = return Undecidable+compareType' _ (DVarT _) = return Undecidable+compareType' DWildCardT _ = return Undecidable+compareType' _ DWildCardT = return Undecidable+compareType' (DForallT tTvBs tCxt t) (DForallT sTvBs sCxt s)+  | length tTvBs == length sTvBs = do+      let dic = M.fromList $ zip (map dtvbToName sTvBs) (map (DVarT . dtvbToName) tTvBs)+      s' <- substTy dic s+      pd <- compareCxt tCxt =<< mapM (substPred dic) sCxt+      bd <- compareType' t s'+      return (pd <> bd)+  | otherwise = return NonEqual+compareType' (DForallT _ _ _) _   = return NonEqual+compareType' (DAppT t1 t2) (DAppT s1 s2)+  = (<>) <$> compareType' t1 s1 <*> compareType' t2 s2+compareType' (DConT t) (DConT s)+  | t == s    = return Equal+  | otherwise = return NonEqual+compareType' (DConT _) _ = return NonEqual+compareType' DArrowT DArrowT = return Equal+compareType' DArrowT _ = return NonEqual+compareType' (DLitT t) (DLitT s)+  | t == s    = return Equal+  | otherwise = return NonEqual+compareType' (DLitT _) _ = return NonEqual+compareType' DStarT DStarT = return NonEqual+compareType' _ _ = return NonEqual++compareCxt :: DCxt -> DCxt -> Q EqlJudge+compareCxt l r = mconcat <$> zipWithM comparePred l r++comparePred :: DPred -> DPred -> Q EqlJudge+comparePred DWildCardPr _ = return Undecidable+comparePred _ DWildCardPr = return Undecidable+comparePred (DVarPr l) (DVarPr r)+  | l == r = return Equal+comparePred (DVarPr _) _ = return Undecidable+comparePred _ (DVarPr _) = return Undecidable+comparePred (DSigPr l t) (DSigPr r s) =+  (<>) <$> compareType' t s <*> comparePred l r+comparePred (DSigPr l _) r = comparePred l r+comparePred l (DSigPr r _) = comparePred l r+comparePred (DAppPr l1 l2) (DAppPr r1 r2) = do+  l2' <- expandType l2+  r2' <- expandType r2+  (<>) <$> comparePred l1 r1 <*> compareType' l2' r2'+comparePred (DAppPr _ _) _ = return NonEqual+comparePred (DConPr l) (DConPr r)+  | l == r = return Equal+  | otherwise = return NonEqual+comparePred (DConPr _) _ = return NonEqual++substPred :: SubstDic -> DPred -> Q DPred+substPred dic (DAppPr p1 p2) = DAppPr <$> substPred dic p1 <*> (expandType =<< substTy dic p2)+substPred dic (DSigPr p knd) = DSigPr <$> substPred dic p  <*> (expandType =<< substTy dic knd)+substPred dic prd@(DVarPr p)+  | Just (DVarT t) <- M.lookup p dic = return $ DVarPr t+  | Just (DConT t) <- M.lookup p dic = return $ DConPr t+  | otherwise = return prd+substPred _ t = return t
equational-reasoning.cabal view
@@ -2,7 +2,7 @@ --  documentation, see http://haskell.org/cabal/users-guide/  name:                equational-reasoning-version:             0.3.0.0+version:             0.4.0.0 synopsis:            Proof assistant for Haskell using DataKinds & PolyKinds description:         A simple convenient library to write equational / preorder proof as in Agda. license:             BSD3@@ -21,11 +21,14 @@  library   exposed-modules:     Proof.Equational, Proof.Propositional, Proof.Induction+                     , Proof.Propositional.Inhabited+                     , Proof.Propositional.Empty   other-modules:       Proof.Internal.THCompat+                     , Proof.Propositional.TH+  ghc-options:         -Wall   build-depends:       base             >= 4      && < 5-               ,       void             >= 0.6    && < 0.8-               ,       template-haskell-  if impl(ghc < 7.10)-    build-depends:     singletons       >= 0.8    && < 1.2-  else-    build-depends:     singletons       >= 2.1    && < 2.3+                     , containers       >= 0.5+                     , template-haskell+                     , th-desugar       >= 1.6+                     , void             >= 0.6    && < 0.8+  build-depends:       singletons       >= 2.1    && < 2.3