packages feed

rerefined 0.7.0 → 0.8.0

raw patch · 6 files changed

+367/−239 lines, 6 filesdep +rerefineddep +type-specPVP ok

version bump matches the API change (PVP)

Dependencies added: rerefined, type-spec

API changes (from Hackage documentation)

- Rerefined.Simplify: type family SimplifyStep p :: Maybe Type
+ Rerefined.Simplify: type AssertSimplified p = AssertSimplified' p TrySimplify p
+ Rerefined.Simplify: type TrySimplify p = TrySimplifyLoop p SimplifyStep p
+ Rerefined.Simplify.Core: type family OrElseNot (mp :: Maybe k) (cont :: Maybe Type) :: Maybe Type

Files

CHANGELOG.md view
@@ -1,3 +1,6 @@+## 0.8.0 (2024-10-12)+* tweak `Simplify` exports (should stay fairly stable now)+ ## 0.7.0 (2024-10-11) * add predicate simplifier at `Rerefined.Simplify`   * old "normalizer" stuff removed
rerefined.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           rerefined-version:        0.7.0+version:        0.8.0 synopsis:       Refinement types, again description:    Please see README.md. category:       Types, Data@@ -54,6 +54,7 @@       Rerefined.Refine       Rerefined.Refine.TH       Rerefined.Simplify+      Rerefined.Simplify.Core       Rerefined.Simplify.Relational   other-modules:       Paths_rerefined@@ -70,7 +71,7 @@       TypeFamilies       DataKinds       MagicHash-  ghc-options: -Wall -Wno-unticked-promoted-constructors+  ghc-options: -fhide-source-paths -Wall   build-depends:       QuickCheck >=2.14 && <2.16     , base >=4.18 && <5@@ -79,4 +80,35 @@     , text >=2.0 && <2.2     , text-builder-linear >=0.1.2 && <0.2     , type-level-show >=0.2.1 && <0.4+  default-language: GHC2021++test-suite spec+  type: exitcode-stdio-1.0+  main-is: Main.hs+  other-modules:+      Paths_rerefined+  hs-source-dirs:+      test+  default-extensions:+      LambdaCase+      NoStarIsType+      DerivingVia+      DeriveAnyClass+      GADTs+      RoleAnnotations+      DefaultSignatures+      TypeFamilies+      DataKinds+      MagicHash+  ghc-options: -fhide-source-paths -Wall+  build-depends:+      QuickCheck >=2.14 && <2.16+    , base >=4.18 && <5+    , mono-traversable >=1.0.17.0 && <1.1+    , rerefined+    , template-haskell >=2.19.0.0 && <2.23+    , text >=2.0 && <2.2+    , text-builder-linear >=0.1.2 && <0.2+    , type-level-show >=0.2.1 && <0.4+    , type-spec >=0.4.0.0 && <0.5   default-language: GHC2021
src/Rerefined/Simplify.hs view
@@ -2,53 +2,30 @@  {- | 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+See 'Rerefined.Simplify.Core' (internal module) for more details. -}  module Rerefined.Simplify   ( Simplify-  , SimplifyStep+  , TrySimplify+  , AssertSimplified   ) 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 )+import Rerefined.Simplify.Core ( SimplifyStep ) --- note that we can't modularize logical simplifications because they're--- mutually recursive with the main simplifier :(+import Data.Kind ( type Constraint )+import GHC.TypeError ( type TypeError, type ErrorMessage(..) )+import Rerefined.Predicate ( type PredicateName )  -- | 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.@@ -62,216 +39,29 @@     -- failed to simplify: give up, return the latest predicate     SimplifyLoop p Nothing   = p --- | Try to perform a single simplification step on the given predicate.+-- | Try to simplify 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+type TrySimplify p = TrySimplifyLoop p (SimplifyStep p) -    SimplifyNot Succeed = Just Fail-    SimplifyNot Fail    = Just Succeed+-- | Simplification loop which returns 'Nothing' for 0 simplifications.+type family TrySimplifyLoop p mp where+    -- got a simplification: continue with the regular simplifier+    TrySimplifyLoop p (Just p') = Just (Simplify' p') -    -- special relational-    SimplifyNot (CompareLength op      n) =-        Just (CompareLength (FlipRelOp op)      n)-    SimplifyNot (CompareValue  op sign n) =-        Just (CompareValue  (FlipRelOp op) sign n)+    -- couldn't simplify+    TrySimplifyLoop p Nothing   = Nothing -    -- recurse-    SimplifyNot p = OrElseNot (SimplifyStep p) Nothing+-- | Assert that a predicate may not be trivially simplified.+--+-- Returns the empty constraint on success, else emits a pretty type error.+--+-- Useful e.g. if you'd like to make sure a user isn't writing silly predicates.+type AssertSimplified p = AssertSimplified' p (TrySimplify p) -type family OrElseNot mp cont where-    OrElseNot (Just p') cont = Just (Not p')-    OrElseNot Nothing   cont = cont+type family AssertSimplified' p mp' :: Constraint where+    AssertSimplified' p Nothing   = ()+    AssertSimplified' p (Just p') = TypeError+        (    Text "Predicate is trivially simplifiable"+        :$$: Text "   " :<>: Text (PredicateName 0 p)+        :$$: Text "-> " :<>: Text (PredicateName 0 p') )
+ src/Rerefined/Simplify/Core.hs view
@@ -0,0 +1,251 @@+{-# LANGUAGE UndecidableInstances #-}++{- | Core predicate simplification algorithm.++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.++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++__Internal module. Exports may change without warning. Try not to use.__+-}++module Rerefined.Simplify.Core 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+  )++-- note that we can't modularize logical simplifications because they're+-- mutually recursive with the main simplifier :(++-- | 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
@@ -1,5 +1,13 @@ {-# LANGUAGE UndecidableInstances #-} +{- | Relational predicate simplification.++These bits aren't mutually recursive with the main simplifier, so we can keep+them separate for a bit of code hygiene.++__Internal module. Exports may change without warning. Try not to use.__+-}+ module Rerefined.Simplify.Relational where  import Rerefined.Predicate.Succeed
+ test/Main.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE AllowAmbiguousTypes #-}++module Main where++import Test.TypeSpec hiding ( And )+import Rerefined.Simplify+import Rerefined.Predicates+import Rerefined.Predicate+import TypeLevelShow.Utils ( type (++) )++-- | Pretty opaque predicate for simplification proofs.+data Opaque+instance Predicate Opaque where type PredicateName d Opaque = "p"++-- | Shorthand for the pretty opaque predicate.+type P = Opaque++main :: IO ()+main = print spec++spec :: Expect+    -- AND identity laws+    (And Fail    P       `SimplifiesTo` Fail+ -/- And P       Fail    `SimplifiesTo` Fail+ -/- And Succeed P       `SimplifiesTo` P+ -/- And P       Succeed `SimplifiesTo` P++     -- OR identity laws+ -/- Or  Succeed P       `SimplifiesTo` Succeed+ -/- Or  P       Succeed `SimplifiesTo` Succeed+ -/- Or  Fail    P       `SimplifiesTo` P+ -/- Or  P       Fail    `SimplifiesTo` P++     -- other+ -/- And (CompareLength RelOpLT 3) (CompareLength RelOpGT 3)+        `SimplifiesTo` Fail+    )+spec = Valid++-- | TODO I'd like to write my own failure message here, but type-spec is+--   complicated.+type SimplifiesTo p p' = It+    (PredicateName 0 p ++ " simplifies to " ++ PredicateName 0 p')+    (TrySimplify p `Is` Just p')