packages feed

witherable 0.2 → 0.3

raw patch · 2 files changed

+76/−24 lines, 2 filesdep +transformers-compatdep ~containers

Dependencies added: transformers-compat

Dependency ranges changed: containers

Files

src/Data/Witherable.hs view
@@ -17,8 +17,6 @@ module Data.Witherable   ( Filterable(..)   , Witherable(..)-  , witherM-  , blightM   , ordNub   , hashNub   , forMaybe@@ -43,13 +41,16 @@ import qualified Data.Map.Lazy as M import qualified Data.Sequence as S import qualified Data.Vector as V-import qualified Data.HashMap.Strict as HM+import qualified Data.HashMap.Lazy as HM import qualified Data.Set as Set import qualified Data.HashSet as HSet import Control.Applicative import qualified Data.Traversable as T import qualified Data.Foldable as F import Data.Functor.Compose+import Data.Functor.Product as P+import Data.Functor.Sum as Sum+import Control.Monad.Trans.Identity import Data.Hashable import Data.Functor.Identity import Control.Monad.Trans.Maybe@@ -59,6 +60,9 @@ #if (MIN_VERSION_base(4,7,0)) import Data.Proxy #endif+#if __GLASGOW_HASKELL__ >= 708+import Data.Coerce (coerce)+#endif import Prelude -- Fix redundant import warning  -- | This type allows combinators to take a 'Filter' specializing the parameter @f@.@@ -87,6 +91,10 @@   {-# INLINE pure #-}   Peat f <*> Peat g = Peat $ \h -> f h <*> g h   {-# INLINE (<*>) #-}+#if MIN_VERSION_base(4,10,0)+  liftA2 f (Peat xs) (Peat ys) = Peat $ \h -> liftA2 f (xs h) (ys h)+  {-# INLINE liftA2 #-}+#endif  -- | Reconstitute a 'Filter' from its monomorphic form. cloneFilter :: FilterLike (Peat a b) s t a b -> Filter s t a b@@ -103,9 +111,19 @@ forMaybeOf = flip {-# INLINE forMaybeOf #-} +-- In case mapMaybeOf or filterOf is called with a function of+-- unknown arity, we don't want to slow things down to raise+-- its arity.+idDot :: (a -> b) -> a -> Identity b+#if __GLASGOW_HASKELL__ >= 708+idDot = coerce+#else+idDot = (Identity .)+#endif+ -- | 'mapMaybe' through a filter. mapMaybeOf :: FilterLike Identity s t a b -> (a -> Maybe b) -> s -> t-mapMaybeOf w f = runIdentity . w (Identity . f)+mapMaybeOf w f = runIdentity . w (idDot f) {-# INLINE mapMaybeOf #-}  -- | 'catMaybes' through a filter.@@ -120,7 +138,7 @@  -- | Filter each element of a structure targeted by a 'Filter'. filterOf :: FilterLike' Identity s a -> (a -> Bool) -> s -> s-filterOf w f = runIdentity . filterAOf w (Identity . f)+filterOf w f = runIdentity . filterAOf w (idDot f) {-# INLINE filterOf #-}  -- | Like 'Functor', but it include 'Maybe' effects.@@ -132,6 +150,9 @@ -- [/identity/] --   @'mapMaybe' Just ≡ id@ --+-- [/conservation/]+--   @'mapMaybe' (Just . f) ≡ 'fmap' f@+-- -- [/composition/] --   @'mapMaybe' f . 'mapMaybe' g ≡ 'mapMaybe' (f <=< g)@ class Functor f => Filterable f where@@ -161,6 +182,9 @@ -- [/identity/] --   @'wither' ('pure' . Just) ≡ 'pure'@ --+-- [/conservation/]+--   @'wither' ('fmap' 'Just' . f) ≡ 'traverse' f@+-- -- [/composition/] --   @'Compose' . 'fmap' ('wither' f) . 'wither' g ≡ 'wither' ('Compose' . 'fmap' ('wither' f) . g)@ --@@ -176,6 +200,17 @@   wither f = fmap catMaybes . T.traverse f   {-# INLINE wither #-} +  -- | @Monadic variant of 'wither'. This may have more efficient implementation.@+  witherM :: Monad m => (a -> m (Maybe b)) -> t a -> m (t b)+#if MIN_VERSION_base(4,8,0)+  witherM = wither+#elif __GLASGOW_HASKELL__ >= 708+  witherM f = unwrapMonad . wither (coerce f)+#else+  witherM f = unwrapMonad . wither (WrapMonad . f)+#endif+  {-# INLINE witherM #-}+   -- | @'Compose' . 'fmap' ('filterA' f) . 'filterA' g ≡ 'filterA' (\x -> 'Compose' $ 'fmap' (\b -> (b&&) <$> f x) (g x)@   filterA :: Applicative f => (a -> f Bool) -> t a -> f (t a)   filterA = filterAOf wither@@ -189,16 +224,6 @@ forMaybe = flip wither {-# INLINE forMaybe #-} --- | A variant of `wither` that works on 'MaybeT'.-witherM :: (Witherable t, Monad m) => (a -> MaybeT m b) -> t a -> m (t b)-witherM f = unwrapMonad . wither (WrapMonad . runMaybeT . f)-{-# INLINE witherM #-}---- | 'blightM' is 'witherM' with its arguments flipped.-blightM :: (Monad m, Witherable t) => t a -> (a -> MaybeT m b) -> m (t b)-blightM = flip witherM-{-# INLINE blightM #-}- -- | Remove the duplicate elements through a filter. ordNubOf :: Ord a => FilterLike' (State (Set.Set a)) s a -> s -> s ordNubOf w t = evalState (w f t) Set.empty@@ -222,14 +247,14 @@ --   occurrence. This is asymptotically faster than using --   'Data.List.nub' from "Data.List". ordNub :: (Witherable t, Ord a) => t a -> t a-ordNub = ordNubOf wither+ordNub = ordNubOf witherM {-# INLINE ordNub #-}  -- | Removes duplicate elements from a list, keeping only the first --   occurrence. This is usually faster than 'ordNub', especially for---   things that have a slow comparion (like 'String').+--   things that have a slow comparison (like 'String'). hashNub :: (Witherable t, Eq a, Hashable a) => t a -> t a-hashNub = hashNubOf wither+hashNub = hashNubOf witherM {-# INLINE hashNub #-}  instance Filterable Maybe where@@ -258,7 +283,7 @@  instance Witherable [] where   wither f = go where-    go (x:xs) = maybe id (:) <$> f x <*> go xs+    go (x:xs) = liftA2 (maybe id (:)) (f x) (go xs)     go [] = pure []   {-# INLINE[0] wither #-} @@ -273,6 +298,9 @@   filter = M.filter  instance Witherable (M.Map k) where+#if MIN_VERSION_containers(0,5,8)+  wither f = M.traverseMaybeWithKey (const f)+#endif  instance (Eq k, Hashable k) => Filterable (HM.HashMap k) where   mapMaybe = HM.mapMaybe@@ -297,8 +325,7 @@   {-# INLINABLE wither #-}  instance Filterable V.Vector where-  mapMaybe f = V.fromList . mapMaybe f . V.toList-  {-# INLINABLE mapMaybe #-}+  mapMaybe = V.mapMaybe  instance Witherable V.Vector where   wither f = fmap V.fromList . wither f . V.toList@@ -312,11 +339,35 @@   wither f = fmap S.fromList . wither f . F.toList   {-# INLINABLE wither #-} +-- The instances for Compose, Product, and Sum are not entirely+-- unique. Any particular composition, product, or sum of functors+-- may support a variety of 'wither' implementations.+ instance (Functor f, Filterable g) => Filterable (Compose f g) where   mapMaybe f = Compose . fmap (mapMaybe f) . getCompose  instance (T.Traversable f, Witherable g) => Witherable (Compose f g) where   wither f = fmap Compose . T.traverse (wither f) . getCompose++instance (Filterable f, Filterable g) => Filterable (P.Product f g) where+  mapMaybe f (P.Pair x y) = P.Pair (mapMaybe f x) (mapMaybe f y)++instance (Witherable f, Witherable g) => Witherable (P.Product f g) where+  wither f (P.Pair x y) = liftA2 P.Pair (wither f x) (wither f y)++instance (Filterable f, Filterable g) => Filterable (Sum.Sum f g) where+  mapMaybe f (Sum.InL x) = Sum.InL (mapMaybe f x)+  mapMaybe f (Sum.InR y) = Sum.InR (mapMaybe f y)++instance (Witherable f, Witherable g) => Witherable (Sum.Sum f g) where+  wither f (Sum.InL x) = Sum.InL <$> wither f x+  wither f (Sum.InR y) = Sum.InR <$> wither f y++instance Filterable f => Filterable (IdentityT f) where+  mapMaybe f (IdentityT m) = IdentityT (mapMaybe f m)++instance Witherable f => Witherable (IdentityT f) where+  wither f (IdentityT m) = IdentityT <$> wither f m  instance Functor f => Filterable (MaybeT f) where   mapMaybe f = MaybeT . fmap (mapMaybe f) . runMaybeT
witherable.cabal view
@@ -1,5 +1,5 @@ name:                witherable-version:             0.2+version:             0.3 synopsis:            filterable traversable description:         A stronger variant of `traverse` which can remove elements and generalised mapMaybe, catMaybes, filter homepage:            https://github.com/fumieval/witherable@@ -12,7 +12,7 @@ build-type:          Simple -- extra-source-files: cabal-version:       >=1.10-tested-With: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2+tested-With: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.3  source-repository head   type: git@@ -24,9 +24,10 @@   -- other-extensions:   build-depends:       base == 4.*,                        base-orphans,-                       containers,+                       containers >= 0.5,                        hashable,                        transformers,+                       transformers-compat,                        unordered-containers,                        vector   hs-source-dirs:      src