packages feed

predicate-transformers 0.3.0.0 → 0.4.0.0

raw patch · 2 files changed

+52/−32 lines, 2 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- PredicateTransformers: checkAll :: Monoid m => [a -> m] -> a -> m
- PredicateTransformers: distF :: (Eq (f ()), Functor f, Foldable f) => f (Pred a) -> Pred (f a)
- PredicateTransformers: getter :: Getting a s a -> FT c a s
- PredicateTransformers: sumOver :: (Monoid m, Plated a) => FT m a a
- PredicateTransformers: type FT c a b = (a -> c) -> (b -> c)
+ PredicateTransformers: allOf1 :: Getting (All, Any) s a -> PT a s
+ PredicateTransformers: allTrue :: [Pred a] -> Pred a
+ PredicateTransformers: kth :: Foldable f => Int -> PT a (f a)
+ PredicateTransformers: list :: [Pred a] -> Pred [a]
- PredicateTransformers: (!) :: (b -> a) -> FT c a b
+ PredicateTransformers: (!) :: (b -> a) -> (a -> c) -> b -> c
- PredicateTransformers: dist :: [Pred a] -> Pred [a]
+ PredicateTransformers: dist :: (Eq (f ()), Functor f, Foldable f) => f (Pred a) -> Pred (f a)
- PredicateTransformers: traced :: Show a => FT c a a
+ PredicateTransformers: traced :: Show a => (a -> c) -> a -> c
- PredicateTransformers: type PT a b = FT Bool a b
+ PredicateTransformers: type PT a b = Pred a -> Pred b

Files

predicate-transformers.cabal view
@@ -1,7 +1,7 @@ cabal-version:       2.4  name:                predicate-transformers-version:             0.3.0.0+version:             0.4.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.
src/PredicateTransformers.hs view
@@ -5,109 +5,129 @@ -- They act as a sort of compositional "matcher language". -- Composing these predicate transformers is meant to be analogous to composing optics -- and there are utilities for using predicate transformers with (`lens`-style) optics.+--+-- Some predicate transformers provided by other libraries:+-- `Data.Foldable.all`, `Data.Foldable.any` (base)+-- `either` (base)+-- `Control.Lens.allOf` (lens)+ 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 Data.Semigroup(All(..), Any(..)) 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.+-- |Predicate transformers form a category where composition is ordinary function composition.+-- Forms a category with `.` and `id`. -- Multiple are already provided by the standard library, -- for instance `Data.Foldable.all` and `Data.Foldable.any`.-type PT a b = FT Bool a b+type PT a b = Pred a -> Pred 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 -> FT c a s-getter g = (view g !)+match p pred = right pred . matching p+{-# inlinable match #-}  -- |Invert a predicate. nay :: PT a a nay = (not .)+{-# inlinable nay #-}  -- |Operate on the `Just` branch of a `Maybe`, or fail. just :: PT a (Maybe a) just = match _Just+{-# inlinable just #-}  -- |Operate on the `Left` branch of an `Either`, or fail. left :: PT e (Either e a) left = match _Left+{-# inlinable left #-}  -- |Operate on the `Right` branch of an `Either`, or fail. right :: PT a (Either e a) right = match _Right+{-# inlinable right #-} --- |Operate on the last value in a list, or fail if it's not present.+-- |Operate on the last value in a foldable, or fail if it's not present. endingWith :: Foldable f => PT a (f a) endingWith _ (toList -> []) = False endingWith p (toList -> xs) = p $ last xs+{-# inlinable endingWith #-} --- |Operate on the first value in a list, or fail if it's not present.+-- |Operate on the first value in a foldable, or fail if it's not present. startingWith :: Foldable f => PT a (f a) startingWith p (toList -> (x:_)) = p x startingWith _ (toList -> []) = False+{-# inlinable startingWith #-} --- |Require that a list has a single element, and operate on that element.+-- |Require that a foldable has a single element, and operate on that element. only :: Foldable f => PT a (f a) only p (toList -> [x]) = p x only _ _ = False+{-# inlinable only #-} +-- |Only test the `k`th element of a foldable.+kth :: Foldable f => Int -> PT a (f a)+kth k p = startingWith p . drop k . toList+{-# inlinable kth #-}+ -- |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]-dist (p:ps) (x:xs) = p x && dist ps xs-dist [] [] = True-dist _ _ = False+list :: [Pred a] -> Pred [a]+list (p:ps) (x:xs) = p x && dist ps xs+list [] [] = True+list _ _ = False+{-# inlinable list #-}  -- |Given a functor-full of predicates, and a functor-full of values, ensure that the structures -- of the two functors match and apply all of the predicates to all of the values.--- Generalized version of `dist`.-distF ::+-- Generalized version of `list`.+dist ::     (Eq (f ()), Functor f, Foldable f) =>     f (Pred a) -> Pred (f a)-distF preds values =+dist preds values =     (() <$ preds) == (() <$ values) &&-    dist (toList preds) (toList values)+    list (toList preds) (toList values)+{-# inlinable dist #-}  -- |Given a representable functor-full of predicates, and a functor-full of values, -- yield a representable functor-full of booleans. Similar to `distF`. distRep :: Representable f =>     f (a -> Bool) -> f a -> f Bool distRep pr fa = tabulate (\r -> index pr r $ index fa r)+{-# inlinable distRep #-}  -- |Test all predicates against one value.-checkAll :: Monoid m => [a -> m] -> a -> m-checkAll ps a = foldMap ($ a) ps+allTrue :: [Pred a] -> Pred a+allTrue ps a = all ($ a) ps+{-# inlinable allTrue #-} --- |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))+-- |Check that a predicate is true for all values behind a generalized getter+-- and that there's at least one value for which it's true.+allOf1 :: Getting (All, Any) s a -> PT a s+allOf1 g p (foldMapOf g (\x -> (All $ p x, Any $ p x)) -> (All a, Any y)) = a && y+{-# inlinable allOf1 #-}  -- |Sugar for tupling. (==>) :: a -> b -> (a, b) (==>) = (,)+{-# inline conlike (==>) #-}  pair :: Pred a -> Pred b -> Pred (a,b) pair f s (a,b) = f a && s b+{-# inline conlike pair #-}  -- |Flipped function composition; `f !` for a function `f` is a predicate transformer.-(!) :: (b -> a) -> FT c a b+(!) :: (b -> a) -> (a -> c) -> b -> c (!) = flip (.)+{-# inline conlike (!) #-}  -- |Prints the input of a predicate, for debugging.-traced :: Show a => FT c a a+traced :: Show a => (a -> c) -> a -> c traced p a = traceShow a (p a)