predicate-transformers 0.2.0.0 → 0.3.0.0
raw patch · 2 files changed
+32/−27 lines, 2 filesdep +mtl
Dependencies added: mtl
Files
- predicate-transformers.cabal +2/−1
- src/PredicateTransformers.hs +30/−26
predicate-transformers.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.4 name: predicate-transformers-version: 0.2.0.0+version: 0.3.0.0 synopsis: A library for writing predicates and transformations over predicates in Haskell description: This package provides ways to write predicates such that they compose nicely and are easy to debug.@@ -24,5 +24,6 @@ build-depends: base ^>=4.11 || ^>=4.12 || ^>=4.13 ,lens ^>=4.17 || ^>=4.18 ,adjunctions ^>=4.2 || ^>=4.3 || ^>=4.4+ ,mtl ^>= 2.2.2 hs-source-dirs: src default-language: Haskell2010
src/PredicateTransformers.hs view
@@ -1,3 +1,5 @@+{-# language ViewPatterns #-}+ -- | This library is based on the notion of a predicate transformer, the below -- type @PT a b@, which is a function from @a@ to predicates on @b@. -- They act as a sort of compositional "matcher language".@@ -6,30 +8,32 @@ module PredicateTransformers where import Control.Lens hiding (index, zoom)+import Control.Monad.Writer(execWriter, tell) import Data.Foldable(toList) import Data.Functor.Rep(Representable(..))+import Data.Semigroup(All(..)) import Debug.Trace -- |A convenient alias for predicates. type Pred a = a -> Bool +-- |Close to a CPS transform of `b -> a`, except that `c` isn't quantified over.+-- Stands for "function transformer".+type FT c a b = (a -> c) -> (b -> c)+ -- |Predicate transformers form a category where composition is ordinary function -- composition. -- Multiple are already provided by the standard library, -- for instance `Data.Foldable.all` and `Data.Foldable.any`.-type PT a b = Pred a -> Pred b---- |Functor from Hask^op to PT.-function :: (b -> a) -> PT a b-function = flip (.)+type PT a b = FT Bool a b -- |Operate on the target of a prism, or fail. match :: APrism s t a b -> PT a s match p pred s = either (const False) pred (matching p s) -- |Operate on the target of a getter.-getter :: Getting a s a -> PT a s-getter g = function (view g)+getter :: Getting a s a -> FT c a s+getter g = (view g !) -- |Invert a predicate. nay :: PT a a@@ -48,24 +52,20 @@ right = match _Right -- |Operate on the last value in a list, or fail if it's not present.-endingWith :: PT a [a]-endingWith _ [] = False-endingWith p xs = p $ last xs+endingWith :: Foldable f => PT a (f a)+endingWith _ (toList -> []) = False+endingWith p (toList -> xs) = p $ last xs -- |Operate on the first value in a list, or fail if it's not present.-startingWith :: PT a [a]-startingWith p (x:_) = p x-startingWith _ [] = False+startingWith :: Foldable f => PT a (f a)+startingWith p (toList -> (x:_)) = p x+startingWith _ (toList -> []) = False -- |Require that a list has a single element, and operate on that element.-only :: PT a [a]-only p [x] = p x+only :: Foldable f => PT a (f a)+only p (toList -> [x]) = p x only _ _ = False --- |Test all predicates against one value.-allTrue :: [Pred a] -> Pred a-allTrue ps a = all ($ a) ps- -- |Given a list of predicates and a list of values, ensure that each predicate holds for each respective value. -- Fails if the two lists have different lengths. dist :: [Pred a] -> Pred [a]@@ -89,6 +89,14 @@ f (a -> Bool) -> f a -> f Bool distRep pr fa = tabulate (\r -> index pr r $ index fa r) +-- |Test all predicates against one value.+checkAll :: Monoid m => [a -> m] -> a -> m+checkAll ps a = foldMap ($ a) ps++-- |Given a plated type, take a monoidal sum over every child recursively, bottom-up.+sumOver :: (Monoid m, Plated a) => FT m a a+sumOver p = execWriter . transformM (\a -> a <$ tell (p a))+ -- |Sugar for tupling. (==>) :: a -> b -> (a, b) (==>) = (,)@@ -96,14 +104,10 @@ pair :: Pred a -> Pred b -> Pred (a,b) pair f s (a,b) = f a && s b -eitherWay :: Pred a -> Pred b -> Pred (Either a b)-eitherWay f _ (Left a) = f a-eitherWay _ g (Right b) = g b---- |Flipped function composition, meant to be used postfix.-(!) :: (b -> a) -> (a -> c) -> b -> c+-- |Flipped function composition; `f !` for a function `f` is a predicate transformer.+(!) :: (b -> a) -> FT c a b (!) = flip (.) -- |Prints the input of a predicate, for debugging.-traced :: Show a => PT a a+traced :: Show a => FT c a a traced p a = traceShow a (p a)