rerefined 0.6.0 → 0.7.0
raw patch · 12 files changed
+395/−108 lines, 12 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Rerefined.Predicate.Logical.Normalize: type family NormLogi p :: Maybe Type
- Rerefined.Predicate.Normalize: type family Norm' p (mp :: Maybe Type)
- Rerefined.Predicate.Relational: type GTE = Or 'GT 'EQ
- Rerefined.Predicate.Relational: type LTE = Or 'LT 'EQ
- Rerefined.Predicate.Relational.Internal: instance Rerefined.Predicate.Relational.Internal.ReifyRelOp 'GHC.Types.EQ
- Rerefined.Predicate.Relational.Internal: instance Rerefined.Predicate.Relational.Internal.ReifyRelOp 'GHC.Types.GT
- Rerefined.Predicate.Relational.Internal: instance Rerefined.Predicate.Relational.Internal.ReifyRelOp 'GHC.Types.LT
- Rerefined.Predicate.Relational.Internal: instance Rerefined.Predicate.Relational.Internal.ReifyRelOp (Rerefined.Predicate.Logical.Or.Or 'GHC.Types.EQ 'GHC.Types.GT)
- Rerefined.Predicate.Relational.Internal: instance Rerefined.Predicate.Relational.Internal.ReifyRelOp (Rerefined.Predicate.Logical.Or.Or 'GHC.Types.EQ 'GHC.Types.LT)
- Rerefined.Predicate.Relational.Internal: instance Rerefined.Predicate.Relational.Internal.ReifyRelOp (Rerefined.Predicate.Logical.Or.Or 'GHC.Types.GT 'GHC.Types.LT)
- Rerefined.Predicate.Relational.Internal: instance Rerefined.Predicate.Relational.Internal.ReifyRelOp Rerefined.Predicate.Relational.Internal.GTE
- Rerefined.Predicate.Relational.Internal: instance Rerefined.Predicate.Relational.Internal.ReifyRelOp Rerefined.Predicate.Relational.Internal.LTE
- Rerefined.Predicate.Relational.Internal: instance Rerefined.Predicate.Relational.Internal.ReifyRelOp Rerefined.Predicate.Relational.Internal.NEQ
- Rerefined.Predicate.Relational.Internal: type GTE = Or 'GT 'EQ
- Rerefined.Predicate.Relational.Internal: type LTE = Or 'LT 'EQ
- Rerefined.Predicate.Relational.Internal: type NEQ = Or 'LT 'GT
- Rerefined.Predicate.Relational.Length: instance forall k (n :: GHC.TypeNats.Nat) (f :: GHC.Types.Type -> GHC.Types.Type) (op :: k). (GHC.TypeNats.KnownNat n, Data.Foldable.Foldable f, Rerefined.Predicate.Relational.Internal.ReifyRelOp op, Rerefined.Predicate.KnownPredicateName (Rerefined.Predicate.Relational.Length.CompareLength op n)) => Rerefined.Predicate.Refine1 (Rerefined.Predicate.Relational.Length.CompareLength op n) f
- Rerefined.Predicate.Relational.Length: instance forall k (n :: GHC.TypeNats.Nat) a (op :: k). (GHC.TypeNats.KnownNat n, Data.MonoTraversable.MonoFoldable a, Rerefined.Predicate.Relational.Internal.ReifyRelOp op, Rerefined.Predicate.KnownPredicateName (Rerefined.Predicate.Relational.Length.CompareLength op n)) => Rerefined.Predicate.Refine (Rerefined.Predicate.Relational.Length.CompareLength op n) a
- Rerefined.Predicate.Relational.Length: instance forall k (op :: k) (n :: GHC.Num.Natural.Natural). Rerefined.Predicate.Predicate (Rerefined.Predicate.Relational.Length.CompareLength op n)
- Rerefined.Predicate.Relational.Value: instance forall k (n :: GHC.TypeNats.Nat) a (op :: k) (sign :: Rerefined.Predicate.Relational.Value.Sign). (GHC.TypeNats.KnownNat n, GHC.Num.Num a, GHC.Classes.Ord a, Rerefined.Predicate.Relational.Internal.ReifyRelOp op, Rerefined.Predicate.Relational.Value.ReifySignedNat sign n, Rerefined.Predicate.KnownPredicateName (Rerefined.Predicate.Relational.Value.CompareValue op sign n)) => Rerefined.Predicate.Refine (Rerefined.Predicate.Relational.Value.CompareValue op sign n) a
- Rerefined.Predicate.Relational.Value: instance forall k (op :: k) (sign :: Rerefined.Predicate.Relational.Value.Sign) (n :: GHC.Num.Natural.Natural). Rerefined.Predicate.Predicate (Rerefined.Predicate.Relational.Value.CompareValue op sign n)
- Rerefined.Predicates: type GTE = Or 'GT 'EQ
- Rerefined.Predicates: type LTE = Or 'LT 'EQ
+ Rerefined.Predicate.Relational: RelOpEQ :: RelOp
+ Rerefined.Predicate.Relational: RelOpGT :: RelOp
+ Rerefined.Predicate.Relational: RelOpGTE :: RelOp
+ Rerefined.Predicate.Relational: RelOpLT :: RelOp
+ Rerefined.Predicate.Relational: RelOpLTE :: RelOp
+ Rerefined.Predicate.Relational: RelOpNEQ :: RelOp
+ Rerefined.Predicate.Relational: data RelOp
+ Rerefined.Predicate.Relational: type family FlipRelOp (op :: RelOp) :: RelOp
+ Rerefined.Predicate.Relational.Internal: RelOpEQ :: RelOp
+ Rerefined.Predicate.Relational.Internal: RelOpGT :: RelOp
+ Rerefined.Predicate.Relational.Internal: RelOpGTE :: RelOp
+ Rerefined.Predicate.Relational.Internal: RelOpLT :: RelOp
+ Rerefined.Predicate.Relational.Internal: RelOpLTE :: RelOp
+ Rerefined.Predicate.Relational.Internal: RelOpNEQ :: RelOp
+ Rerefined.Predicate.Relational.Internal: data RelOp
+ Rerefined.Predicate.Relational.Internal: instance Rerefined.Predicate.Relational.Internal.ReifyRelOp 'Rerefined.Predicate.Relational.Internal.RelOpEQ
+ Rerefined.Predicate.Relational.Internal: instance Rerefined.Predicate.Relational.Internal.ReifyRelOp 'Rerefined.Predicate.Relational.Internal.RelOpGT
+ Rerefined.Predicate.Relational.Internal: instance Rerefined.Predicate.Relational.Internal.ReifyRelOp 'Rerefined.Predicate.Relational.Internal.RelOpGTE
+ Rerefined.Predicate.Relational.Internal: instance Rerefined.Predicate.Relational.Internal.ReifyRelOp 'Rerefined.Predicate.Relational.Internal.RelOpLT
+ Rerefined.Predicate.Relational.Internal: instance Rerefined.Predicate.Relational.Internal.ReifyRelOp 'Rerefined.Predicate.Relational.Internal.RelOpLTE
+ Rerefined.Predicate.Relational.Internal: instance Rerefined.Predicate.Relational.Internal.ReifyRelOp 'Rerefined.Predicate.Relational.Internal.RelOpNEQ
+ Rerefined.Predicate.Relational.Length: instance (GHC.TypeNats.KnownNat n, Data.Foldable.Foldable f, Rerefined.Predicate.Relational.Internal.ReifyRelOp op, Rerefined.Predicate.KnownPredicateName (Rerefined.Predicate.Relational.Length.CompareLength op n)) => Rerefined.Predicate.Refine1 (Rerefined.Predicate.Relational.Length.CompareLength op n) f
+ Rerefined.Predicate.Relational.Length: instance (GHC.TypeNats.KnownNat n, Data.MonoTraversable.MonoFoldable a, Rerefined.Predicate.Relational.Internal.ReifyRelOp op, Rerefined.Predicate.KnownPredicateName (Rerefined.Predicate.Relational.Length.CompareLength op n)) => Rerefined.Predicate.Refine (Rerefined.Predicate.Relational.Length.CompareLength op n) a
+ Rerefined.Predicate.Relational.Length: instance Rerefined.Predicate.Predicate (Rerefined.Predicate.Relational.Length.CompareLength op n)
+ Rerefined.Predicate.Relational.Value: instance (GHC.TypeNats.KnownNat n, GHC.Num.Num a, GHC.Classes.Ord a, Rerefined.Predicate.Relational.Internal.ReifyRelOp op, Rerefined.Predicate.Relational.Value.ReifySignedNat sign n, Rerefined.Predicate.KnownPredicateName (Rerefined.Predicate.Relational.Value.CompareValue op sign n)) => Rerefined.Predicate.Refine (Rerefined.Predicate.Relational.Value.CompareValue op sign n) a
+ Rerefined.Predicate.Relational.Value: instance Rerefined.Predicate.Predicate (Rerefined.Predicate.Relational.Value.CompareValue op sign n)
+ Rerefined.Predicates: RelOpEQ :: RelOp
+ Rerefined.Predicates: RelOpGT :: RelOp
+ Rerefined.Predicates: RelOpGTE :: RelOp
+ Rerefined.Predicates: RelOpLT :: RelOp
+ Rerefined.Predicates: RelOpLTE :: RelOp
+ Rerefined.Predicates: RelOpNEQ :: RelOp
+ Rerefined.Predicates: data RelOp
+ Rerefined.Simplify: type Simplify p = Simplify' p
+ Rerefined.Simplify: type family SimplifyStep p :: Maybe Type
+ Rerefined.Simplify.Relational: type family SimplifyCompareLengthOr (lop :: RelOp) (ln :: Natural) (rop :: RelOp) (rn :: Natural) :: Maybe Type
- Rerefined.Predicate.Relational: data CompareLength (op :: k) (n :: Natural)
+ Rerefined.Predicate.Relational: data CompareLength (op :: RelOp) (n :: Natural)
- Rerefined.Predicate.Relational: data CompareValue (op :: k) (sign :: Sign) (n :: Natural)
+ Rerefined.Predicate.Relational: data CompareValue (op :: RelOp) (sign :: Sign) (n :: Natural)
- Rerefined.Predicate.Relational.Internal: class ReifyRelOp (op :: k) where {
+ Rerefined.Predicate.Relational.Internal: class ReifyRelOp (op :: RelOp) where {
- Rerefined.Predicate.Relational.Internal: type ShowRelOp (op :: k) :: Symbol;
+ Rerefined.Predicate.Relational.Internal: type ShowRelOp (op :: RelOp) :: Symbol;
- Rerefined.Predicate.Relational.Internal: type family NormalizeOrRelOp op
+ Rerefined.Predicate.Relational.Internal: type family FlipRelOp (op :: RelOp) :: RelOp
- Rerefined.Predicate.Relational.Length: data CompareLength (op :: k) (n :: Natural)
+ Rerefined.Predicate.Relational.Length: data CompareLength (op :: RelOp) (n :: Natural)
- Rerefined.Predicate.Relational.Length: type WROE (op :: k) (n :: Natural) (m :: Natural) = WROE' op n m WidenRelOp op n m
+ Rerefined.Predicate.Relational.Length: type WROE (op :: RelOp) (n :: Natural) (m :: Natural) = WROE' op n m WidenRelOp op n m
- Rerefined.Predicate.Relational.Length: validateCompareLength :: forall {k} (op :: k) (n :: Nat). (KnownNat n, ReifyRelOp op, KnownPredicateName (CompareLength op n)) => Proxy# (CompareLength op n) -> Int -> Maybe RefineFailure
+ Rerefined.Predicate.Relational.Length: validateCompareLength :: forall (op :: RelOp) (n :: Nat). (KnownNat n, ReifyRelOp op, KnownPredicateName (CompareLength op n)) => Proxy# (CompareLength op n) -> Int -> Maybe RefineFailure
- Rerefined.Predicate.Relational.Length: widenCompareLength :: forall {k} (m :: Natural) (op :: k) (n :: Natural) a. WROE op n m => Refined (CompareLength op n) a -> Refined (CompareLength op m) a
+ Rerefined.Predicate.Relational.Length: widenCompareLength :: forall (m :: Natural) (op :: RelOp) (n :: Natural) a. WROE op n m => Refined (CompareLength op n) a -> Refined (CompareLength op m) a
- Rerefined.Predicate.Relational.Length: widenCompareLength1 :: forall {k} {k1} (m :: Natural) (op :: k) (n :: Natural) (f :: k1 -> Type) (a :: k1). WROE op n m => Refined1 (CompareLength op n) f a -> Refined1 (CompareLength op m) f a
+ Rerefined.Predicate.Relational.Length: widenCompareLength1 :: forall {k1} (m :: Natural) (op :: RelOp) (n :: Natural) (f :: k1 -> Type) (a :: k1). WROE op n m => Refined1 (CompareLength op n) f a -> Refined1 (CompareLength op m) f a
- Rerefined.Predicate.Relational.Value: data CompareValue (op :: k) (sign :: Sign) (n :: Natural)
+ Rerefined.Predicate.Relational.Value: data CompareValue (op :: RelOp) (sign :: Sign) (n :: Natural)
- Rerefined.Predicates: data CompareLength (op :: k) (n :: Natural)
+ Rerefined.Predicates: data CompareLength (op :: RelOp) (n :: Natural)
- Rerefined.Predicates: data CompareValue (op :: k) (sign :: Sign) (n :: Natural)
+ Rerefined.Predicates: data CompareValue (op :: RelOp) (sign :: Sign) (n :: Natural)
- Rerefined.Predicates.Operators: type (.>) = 'GT
+ Rerefined.Predicates.Operators: type (.>) = 'RelOpGT
Files
- CHANGELOG.md +4/−0
- rerefined.cabal +3/−3
- src/Rerefined/Predicate/Logical/Normalize.hs +0/−10
- src/Rerefined/Predicate/Normalize.hs +0/−12
- src/Rerefined/Predicate/Relational.hs +4/−2
- src/Rerefined/Predicate/Relational/Internal.hs +48/−72
- src/Rerefined/Predicate/Relational/Length.hs +1/−1
- src/Rerefined/Predicate/Relational/Value.hs +1/−1
- src/Rerefined/Predicates.hs +1/−1
- src/Rerefined/Predicates/Operators.hs +6/−6
- src/Rerefined/Simplify.hs +277/−0
- src/Rerefined/Simplify/Relational.hs +50/−0
CHANGELOG.md view
@@ -1,3 +1,7 @@+## 0.7.0 (2024-10-11)+* add predicate simplifier at `Rerefined.Simplify`+ * old "normalizer" stuff removed+ ## 0.6.0 (2024-10-01) * remove `Via` predicate, only need `validateVia` * swap `validateBool` args
rerefined.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack name: rerefined-version: 0.6.0+version: 0.7.0 synopsis: Refinement types, again description: Please see README.md. category: Types, Data@@ -40,11 +40,9 @@ Rerefined.Predicate.Logical.Iff Rerefined.Predicate.Logical.Nand Rerefined.Predicate.Logical.Nor- Rerefined.Predicate.Logical.Normalize Rerefined.Predicate.Logical.Not Rerefined.Predicate.Logical.Or Rerefined.Predicate.Logical.Xor- Rerefined.Predicate.Normalize Rerefined.Predicate.Relational Rerefined.Predicate.Relational.Internal Rerefined.Predicate.Relational.Length@@ -55,6 +53,8 @@ Rerefined.Predicates.Operators Rerefined.Refine Rerefined.Refine.TH+ Rerefined.Simplify+ Rerefined.Simplify.Relational other-modules: Paths_rerefined hs-source-dirs:
− src/Rerefined/Predicate/Logical/Normalize.hs
@@ -1,10 +0,0 @@-module Rerefined.Predicate.Logical.Normalize where--import Rerefined.Predicate.Logical--type family NormLogi p where- NormLogi (Not (Not p)) = Just p- NormLogi (Or l l) = Just l- NormLogi (And l l) = Just l- NormLogi (Nand l l) = Just (Not l)- NormLogi p = Nothing
− src/Rerefined/Predicate/Normalize.hs
@@ -1,12 +0,0 @@-{-# LANGUAGE UndecidableInstances #-}--module Rerefined.Predicate.Normalize where--import Rerefined.Predicate.Logical.Normalize--type family Norm p where- Norm p = Norm' p (NormLogi p)--type family Norm' p mp where- Norm' p Nothing = p- Norm' p (Just p') = Norm p'
src/Rerefined/Predicate/Relational.hs view
@@ -1,8 +1,10 @@ module Rerefined.Predicate.Relational- ( CompareValue+ ( RelOp(..)+ , CompareValue , Sign(..) , CompareLength- , LTE, GTE+ , WidenRelOp+ , FlipRelOp ) where import Rerefined.Predicate.Relational.Internal
src/Rerefined/Predicate/Relational/Internal.hs view
@@ -1,111 +1,87 @@ {-# LANGUAGE AllowAmbiguousTypes #-} -- for ReifyRelOp {-# LANGUAGE UndecidableInstances #-} -- for WidenRelOp -{- | Relational operator definitions.--Haskell base exports the type 'Ordering', which is an enum that states the-result of comparing two 'Ord's. We can utilize this to define /relational-operators/:--* 'LT', 'EQ' and 'GT' already map to relational operators.-* The others can be defined by combining the above with 'Or'. e.g. @'LT' ``Or``- 'EQ'@ -> "less than or equal" ('<=')--What's the point? We save on definitions, and get to reuse well-known data types-which most users will have intuition for. We do have to contest with-commutativity, but this is an extremely minor concern which can only come up if-you don't use the provided type synonyms, or do lots of type-level predicate-manipulation. And we provide those swapped-order instances anyway!--}+-- | Relational operator definitions. module Rerefined.Predicate.Relational.Internal where -import Rerefined.Predicate.Logical.Or import GHC.TypeNats import Data.Type.Ord ( OrdCond ) import GHC.TypeLits ( Symbol ) -import Data.Kind ( Type )--type LTE = LT `Or` EQ+{- | Relational operator. --- | "not equal to" is equivalent to "strictly less than or greater than". We--- could use 'Rerefined.Predicate.Logical.Not.Not', but sticking with just--- 'Or' keeps the internals simple.-type NEQ = LT `Or` GT+Constructor order is arbitrary due to @NEQ@, which obstructs ordering in a+meaningful way. -type GTE = GT `Or` EQ+Note that these operators may be defined by combining 'Ordering's in certain+ways: for example @'LT' OR 'EQ'@ could be @LTE@, @'LT' OR 'GT'@ could be @NEQ@.+This is convenient for user intuition, permitting the use of e.g. 'LT' as a+relational operator directly. However, it complicates type-level work, as now we+can't restrict relational operators to a given kind, and we have to handle+non-standard orderings like @'GT' OR 'LT'@.+-}+data RelOp+ = RelOpEQ -- ^ @==@ equal to+ | RelOpNEQ -- ^ @/=@ less than or greater than (also not equal to)+ | RelOpLT -- ^ @<@ less than+ | RelOpLTE -- ^ @<=@ less than or equal to+ | RelOpGTE -- ^ @>=@ equal to or greater than+ | RelOpGT -- ^ @>@ greater than --- | Reify a relational operator type tag.------ Permitted operators are @Ordering@ constructors 'LT', 'EQ' and 'GT'; and--- combinations of these using 'Or'.-class ReifyRelOp op where+-- | Reify a 'RelOp'.+class ReifyRelOp (op :: RelOp) where -- | Pretty @op@. type ShowRelOp op :: Symbol - -- | The term-level relational operator that @op@ describes.+ -- | The term-level relational operator that @op :: 'RelOp'@ describes. reifyRelOp :: forall a. Ord a => a -> a -> Bool -instance ReifyRelOp LT where- type ShowRelOp LT = "<"+instance ReifyRelOp RelOpLT where+ type ShowRelOp RelOpLT = "<" reifyRelOp = (<) -instance ReifyRelOp LTE where- type ShowRelOp LTE = "<="+instance ReifyRelOp RelOpLTE where+ type ShowRelOp RelOpLTE = "<=" reifyRelOp = (<=) --- | Hidden instance. You won't see this if you use the type synonyms.-deriving via LTE instance ReifyRelOp (EQ `Or` LT)--instance ReifyRelOp EQ where- type ShowRelOp EQ = "=="+instance ReifyRelOp RelOpEQ where+ type ShowRelOp RelOpEQ = "==" reifyRelOp = (==) -instance ReifyRelOp NEQ where- type ShowRelOp NEQ = "/="+instance ReifyRelOp RelOpNEQ where+ type ShowRelOp RelOpNEQ = "/=" reifyRelOp = (/=) --- | Hidden instance. You won't see this if you use the type synonyms.-deriving via NEQ instance ReifyRelOp (GT `Or` LT)--instance ReifyRelOp GTE where- type ShowRelOp GTE = ">="+instance ReifyRelOp RelOpGTE where+ type ShowRelOp RelOpGTE = ">=" reifyRelOp = (>=) --- | Hidden instance. You won't see this if you use the type synonyms.-deriving via GTE instance ReifyRelOp (EQ `Or` GT)--instance ReifyRelOp GT where- type ShowRelOp GT = ">"+instance ReifyRelOp RelOpGT where+ type ShowRelOp RelOpGT = ">" reifyRelOp = (>) -- | Can we widen the given 'RelOp' on the given 'Natural' from @n@ to @m@?-type WidenRelOp :: k -> Natural -> Natural -> Bool+type WidenRelOp :: RelOp -> Natural -> Natural -> Bool type family WidenRelOp op n m where -- @n == m@? no problem WidenRelOp op n n = True -- I'd love to simplify this, but 'CmpNat' is opaque.- WidenRelOp LT n m = OrdCond (CmpNat n m) True True False- WidenRelOp LTE n m = OrdCond (CmpNat n m) True True False- WidenRelOp GTE n m = OrdCond (CmpNat n m) False True True- WidenRelOp GT n m = OrdCond (CmpNat n m) False True True-- -- | swapped LTE, lower down in equation list because less common- WidenRelOp (EQ `Or` LT) n m =- OrdCond (CmpNat n m) True True False-- -- | swapped GTE, lower down in equation list because less common- WidenRelOp (EQ `Or` GT) n m =- OrdCond (CmpNat n m) False True True+ WidenRelOp RelOpLT n m = OrdCond (CmpNat n m) True True False+ WidenRelOp RelOpLTE n m = OrdCond (CmpNat n m) True True False+ WidenRelOp RelOpGTE n m = OrdCond (CmpNat n m) False True True+ WidenRelOp RelOpGT n m = OrdCond (CmpNat n m) False True True -- can't widen (==) or (/=)- WidenRelOp _ _ _ = False+ WidenRelOp op n m = False --- this gets clumsier due to kinding clashes (k vs. Ordering)-type NormalizeOrRelOp :: Type -> Type-type family NormalizeOrRelOp op where- NormalizeOrRelOp (EQ `Or` LT) = LTE- NormalizeOrRelOp (GT `Or` LT) = NEQ- NormalizeOrRelOp (EQ `Or` GT) = GTE+-- | Flip a 'RelOp' to give the opposite comparison.+type FlipRelOp :: RelOp -> RelOp+type family FlipRelOp op where+ FlipRelOp RelOpEQ = RelOpNEQ+ FlipRelOp RelOpNEQ = RelOpEQ+ FlipRelOp RelOpLT = RelOpGTE+ FlipRelOp RelOpLTE = RelOpGT+ FlipRelOp RelOpGTE = RelOpLT+ FlipRelOp RelOpGT = RelOpLTE
src/Rerefined/Predicate/Relational/Length.hs view
@@ -17,7 +17,7 @@ import Data.Text.Builder.Linear qualified as TBL -- | Compare length to a type-level 'Natural' using the given 'RelOp'.-data CompareLength op (n :: Natural)+data CompareLength (op :: RelOp) (n :: Natural) -- | Precedence of 4 (matching base relational operators e.g. '>='). instance Predicate (CompareLength op n) where
src/Rerefined/Predicate/Relational/Value.hs view
@@ -12,7 +12,7 @@ import GHC.TypeLits ( Symbol ) -- | Compare value to a type-level 'Natural' using the given 'RelOp'.-data CompareValue op (sign :: Sign) (n :: Natural)+data CompareValue (op :: RelOp) (sign :: Sign) (n :: Natural) -- | Precedence of 4 (matching base relational operators e.g. '>='). instance Predicate (CompareValue op sign n) where
src/Rerefined/Predicates.hs view
@@ -11,10 +11,10 @@ , And, Iff, If, Nand, Nor, Not, Or, Xor -- * Relational+ , RelOp(..) , CompareValue , Sign(..) , CompareLength- , LTE, GTE ) where import Rerefined.Predicate.Succeed
src/Rerefined/Predicates/Operators.hs view
@@ -59,9 +59,9 @@ type (.->) = If infix 4 .<, .<=, .==, ./=, .>=, .>-type (.<) = LT-type (.<=) = LTE-type (.==) = EQ-type (./=) = NEQ-type (.>=) = GTE-type (.>) = GT+type (.<) = RelOpLT+type (.<=) = RelOpLTE+type (.==) = RelOpEQ+type (./=) = RelOpNEQ+type (.>=) = RelOpGTE+type (.>) = RelOpGT
+ src/Rerefined/Simplify.hs view
@@ -0,0 +1,277 @@+{-# LANGUAGE UndecidableInstances #-}++{- | Primitive predicate simplifier.++This is related to an NP-complete problem (see Boolean satisfiability problem).+We focus on /immediate, operation-reducing simplifications/, and hope that the+input is formed in such a way that our rules match.++In short, the simplifier is largely contextless. It inspects (usually) a single+layer/depth at a time. So we can consistently simplify things like logical+identities. But don't expect simplifications hard to spot with the naked eye.++The simplifier may not be expectected to consistently implement any+transformations whatsoever. The only guarantees are++* the output has the same or fewer operations+* the output meaning is identical to the input++Implementation pitfalls:++* not extensible: only works for built-in logical & relational predicates+* no protection against non-termination e.g. if a pair of transformations loop+* very tedious to write. that's life+-}++module Rerefined.Simplify+ ( Simplify+ , SimplifyStep+ ) where++import Rerefined.Predicate.Succeed+import Rerefined.Predicate.Fail++import Rerefined.Predicate.Logical++import Rerefined.Predicate.Relational ( CompareLength, CompareValue, FlipRelOp )+import Rerefined.Simplify.Relational+ ( SimplifyCompareLength+ , SimplifyCompareLengthAnd+ , SimplifyCompareLengthOr+ )++import Data.Kind ( Type )++-- note that we can't modularize logical simplifications because they're+-- mutually recursive with the main simplifier :(++-- | Simplify the given predicate.+--+-- Returns the input predicate if we were unable to simplify.+type Simplify :: Type -> Type+type Simplify p = Simplify' p++-- | Helper definition for reducing duplication.+type Simplify' p = SimplifyLoop p (SimplifyStep p)++-- | Simplification loop.+type family SimplifyLoop p mp where+ -- simplification step succeeded: try again on the simplified predicate+ SimplifyLoop p (Just p') = Simplify' p'++ -- failed to simplify: give up, return the latest predicate+ SimplifyLoop p Nothing = p++-- | Try to perform a single simplification step on the given predicate.+--+-- Returns 'Nothing' if we were unable to simplify.+type family SimplifyStep p where+ SimplifyStep (Not p) = SimplifyNot p++ SimplifyStep (And l r) = SimplifyAnd l r+ SimplifyStep (Or l r) = SimplifyOr l r+ SimplifyStep (Nand l r) = SimplifyNand l r+ SimplifyStep (Nor l r) = SimplifyNor l r+ SimplifyStep (Iff l r) = SimplifyIff l r+ SimplifyStep (Xor l r) = SimplifyXor l r+ SimplifyStep (If l r) = SimplifyIf l r++ SimplifyStep (CompareLength op n) = SimplifyCompareLength op n+ -- Don't think we can do anything for CompareValue.++ SimplifyStep p = Nothing++type family SimplifyAnd l r where+ -- identity laws+ SimplifyAnd p Fail = Just Fail+ SimplifyAnd Fail p = Just Fail+ SimplifyAnd p Succeed = Just p+ SimplifyAnd Succeed p = Just p++ SimplifyAnd p p = Just p++ -- distributivity+ SimplifyAnd (Or x y) (Or x z) = Just (Or x (And y z))++ -- special+ SimplifyAnd (CompareLength lop ln) (CompareLength rop rn) =+ SimplifyCompareLengthAnd lop ln rop rn++ -- recurse+ SimplifyAnd l r =+ (OrElseAndL r (SimplifyStep l)+ (OrElseAndR l (SimplifyStep r)+ Nothing))++type family OrElseAndL r mp cont where+ OrElseAndL r Nothing cont = cont+ OrElseAndL r (Just l') cont = Just (And l' r)++type family OrElseAndR l mp cont where+ OrElseAndR l Nothing cont = cont+ OrElseAndR l (Just r') cont = Just (And l r')++type family SimplifyOr l r where+ -- identity laws+ SimplifyOr Succeed p = Just Succeed+ SimplifyOr p Succeed = Just Succeed+ SimplifyOr Fail p = Just p+ SimplifyOr p Fail = Just p++ SimplifyOr p p = Just p++ -- distributivity+ SimplifyOr (And x y) (And x z) = Just (And x (Or y z))++ -- special relational+ SimplifyOr (CompareLength lop ln) (CompareLength rop rn) =+ SimplifyCompareLengthOr lop ln rop rn++ -- recurse+ SimplifyOr l r =+ (OrElseOrL r (SimplifyStep l)+ (OrElseOrR l (SimplifyStep r)+ Nothing))++type family OrElseOrL r mp cont where+ OrElseOrL r Nothing cont = cont+ OrElseOrL r (Just l') cont = Just (Or l' r)++type family OrElseOrR l mp cont where+ OrElseOrR l Nothing cont = cont+ OrElseOrR l (Just r') cont = Just (Or l r')++type family SimplifyNand l r where+ -- identity laws+ SimplifyNand Fail p = Just Succeed+ SimplifyNand p Fail = Just Succeed+ SimplifyNand Succeed p = Just (Not p)+ SimplifyNand p Succeed = Just (Not p)++ SimplifyNand p p = Just (Not p)++ -- recurse+ SimplifyNand l r =+ (OrElseNandL r (SimplifyStep l)+ (OrElseNandR l (SimplifyStep r)+ Nothing))++type family OrElseNandL r mp cont where+ OrElseNandL r Nothing cont = cont+ OrElseNandL r (Just l') cont = Just (Nand l' r)++type family OrElseNandR l mp cont where+ OrElseNandR l Nothing cont = cont+ OrElseNandR l (Just r') cont = Just (Nand l r')++type family SimplifyNor l r where+ -- identity laws+ SimplifyNor Succeed p = Just Fail+ SimplifyNor p Succeed = Just Fail+ SimplifyNor Fail p = Just (Not p)+ SimplifyNor p Fail = Just (Not p)++ SimplifyNor p p = Just (Not p)++ -- recurse+ SimplifyNor l r =+ (OrElseNorL r (SimplifyStep l)+ (OrElseNorR l (SimplifyStep r)+ Nothing))++type family OrElseNorL r mp cont where+ OrElseNorL r Nothing cont = cont+ OrElseNorL r (Just l') cont = Just (Nor l' r)++type family OrElseNorR l mp cont where+ OrElseNorR l Nothing cont = cont+ OrElseNorR l (Just r') cont = Just (Nor l r')++type family SimplifyXor l r where+ -- identity laws+ SimplifyXor Fail p = Just p+ SimplifyXor p Fail = Just p+ SimplifyXor Succeed p = Just (Not p)+ SimplifyXor p Succeed = Just (Not p)++ SimplifyXor p p = Just Fail++ -- recurse+ SimplifyXor l r =+ (OrElseXorL r (SimplifyStep l)+ (OrElseXorR l (SimplifyStep r)+ Nothing))++type family OrElseXorL r mp cont where+ OrElseXorL r Nothing cont = cont+ OrElseXorL r (Just l') cont = Just (Xor l' r)++type family OrElseXorR l mp cont where+ OrElseXorR l Nothing cont = cont+ OrElseXorR l (Just r') cont = Just (Xor l r')++type family SimplifyIf l r where+ -- identity laws+ SimplifyIf Fail p = Just Succeed+ SimplifyIf p Fail = Just Succeed+ SimplifyIf Succeed p = Just p+ SimplifyIf p Succeed = Just p++ SimplifyIf p p = Just Succeed++ -- recurse+ SimplifyIf l r =+ (OrElseIfL r (SimplifyStep l)+ (OrElseIfR l (SimplifyStep r)+ Nothing))++type family OrElseIfL r mp cont where+ OrElseIfL r Nothing cont = cont+ OrElseIfL r (Just l') cont = Just (If l' r)++type family OrElseIfR l mp cont where+ OrElseIfR l Nothing cont = cont+ OrElseIfR l (Just r') cont = Just (If l r')++type family SimplifyIff l r where+ -- identity laws+ SimplifyIff Succeed p = Just p+ SimplifyIff p Succeed = Just p+ SimplifyIff Fail p = Just (Not p)+ SimplifyIff p Fail = Just (Not p)++ SimplifyIff p p = Just Succeed++ -- recurse+ SimplifyIff l r =+ (OrElseIffL r (SimplifyStep l)+ (OrElseIffR l (SimplifyStep r)+ Nothing))++type family OrElseIffL r mp cont where+ OrElseIffL r Nothing cont = cont+ OrElseIffL r (Just l') cont = Just (Iff l' r)++type family OrElseIffR l mp cont where+ OrElseIffR l Nothing cont = cont+ OrElseIffR l (Just r') cont = Just (Iff l r')++type family SimplifyNot p where+ -- double negation+ SimplifyNot (Not p) = Just p++ SimplifyNot Succeed = Just Fail+ SimplifyNot Fail = Just Succeed++ -- special relational+ SimplifyNot (CompareLength op n) =+ Just (CompareLength (FlipRelOp op) n)+ SimplifyNot (CompareValue op sign n) =+ Just (CompareValue (FlipRelOp op) sign n)++ -- recurse+ SimplifyNot p = OrElseNot (SimplifyStep p) Nothing++type family OrElseNot mp cont where+ OrElseNot (Just p') cont = Just (Not p')+ OrElseNot Nothing cont = cont
+ src/Rerefined/Simplify/Relational.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE UndecidableInstances #-}++module Rerefined.Simplify.Relational where++import Rerefined.Predicate.Succeed+import Rerefined.Predicate.Fail++import Rerefined.Predicate.Relational+import GHC.TypeNats ( Natural, CmpNat )+import Data.Type.Ord ( OrdCond )++type family SimplifyCompareLength (op :: RelOp) (n :: Natural) where+ SimplifyCompareLength RelOpLT 0 = Just Fail+ SimplifyCompareLength RelOpLTE 0 = Just (CompareLength RelOpEQ 0)+ SimplifyCompareLength RelOpGTE 0 = Just Succeed+ SimplifyCompareLength RelOpGT 0 = Just (CompareLength RelOpEQ 0)++ SimplifyCompareLength op n = Nothing++type family SimplifyCompareLengthAnd+ (lop :: RelOp) (ln :: Natural) (rop :: RelOp) (rn :: Natural) where+ -- @<n AND >m@: @n<=m@ -> False+ SimplifyCompareLengthAnd RelOpLT n RelOpGT m =+ OrdCond (CmpNat n m)+ (Just Fail)+ (Just Fail)+ Nothing+ SimplifyCompareLengthAnd RelOpGT m RelOpLT n =+ OrdCond (CmpNat n m)+ (Just Fail)+ (Just Fail)+ Nothing++ SimplifyCompareLengthAnd lop ln rop rn = Nothing++type family SimplifyCompareLengthOr+ (lop :: RelOp) (ln :: Natural) (rop :: RelOp) (rn :: Natural) where+ -- @<n OR >m@: @n==m@ -> NEQ; @n>m@ -> True (?)+ SimplifyCompareLengthOr RelOpLT n RelOpGT m =+ OrdCond (CmpNat n m)+ Nothing+ (Just (CompareLength RelOpNEQ n))+ (Just Succeed)+ SimplifyCompareLengthOr RelOpGT m RelOpLT n =+ OrdCond (CmpNat n m)+ Nothing+ (Just (CompareLength RelOpNEQ n))+ (Just Succeed)++ SimplifyCompareLengthOr lop ln rop rn = Nothing