packages feed

witherable 0.1.2.1 → 0.1.2.2

raw patch · 2 files changed

+33/−18 lines, 2 files

Files

src/Data/Witherable.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP #-}
+{-# LANGUAGE CPP, DeriveFunctor, DeriveFoldable, DeriveTraversable, StandaloneDeriving, UndecidableInstances, FlexibleContexts #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Witherable
@@ -6,10 +6,9 @@ -- License     :  BSD3
 --
 -- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
--- Stability   :  experimental
+-- Stability   :  provisional
 -- Portability :  non-portable
 --
--- This module generalizes filterable containers.
 -----------------------------------------------------------------------------
 module Data.Witherable where
 import qualified Data.Maybe as Maybe
@@ -45,8 +44,9 @@ --
 --   @t . 'wither' f = 'wither' (t . f)@
 --
--- Minimal complete definition: `wither` or `catMaybes`.
--- The default definitions can be overriden for efficiency.
+-- Minimal complete definition: `wither` or `mapMaybe` or `catMaybes`.
+-- The default definitions can be overridden for efficiency.
+
 class T.Traversable t => Witherable t where
 
   wither :: Applicative f => (a -> f (Maybe b)) -> t a -> f (t b)
@@ -87,34 +87,34 @@   {-# INLINABLE wither #-}
 
 instance Witherable [] where
-  wither f = fmap Maybe.catMaybes . T.traverse f
-  {-# INLINABLE wither #-}
+  wither f = go where
+    go (x:xs) = maybe id (:) <$> f x <*> go xs
+    go [] = pure []
+  {-# INLINE wither #-}
+  mapMaybe = Maybe.mapMaybe
+  {-# INLINE mapMaybe #-}
   catMaybes = Maybe.catMaybes
-  {-# INLINABLE catMaybes #-}
+  {-# INLINE catMaybes #-}
   filter = Prelude.filter
-  {-# INLINABLE filter #-}
+  {-# INLINE filter #-}
 
 instance Witherable IM.IntMap where
-  wither f = fmap IM.fromAscList . wither (\(i, a) -> fmap ((,) i) <$> f a) . IM.toList
-  {-# INLINABLE wither #-}
   mapMaybe = IM.mapMaybe
   {-# INLINE mapMaybe #-}
   filter = IM.filter
   {-# INLINE filter #-}
 
 instance Ord k => Witherable (M.Map k) where
-  wither f = fmap M.fromAscList . wither (\(i, a) -> fmap ((,) i) <$> f a) . M.toList
-  {-# INLINABLE wither #-}
   mapMaybe = M.mapMaybe
   {-# INLINE mapMaybe #-}
   filter = M.filter
-  {-# INLINABLE filter #-}
+  {-# INLINE filter #-}
 
 instance (Eq k, Hashable k) => Witherable (HM.HashMap k) where
   wither f = fmap HM.fromList . wither (\(i, a) -> fmap ((,) i) <$> f a) . HM.toList
   {-# INLINABLE wither #-}
   filter = HM.filter
-  {-# INLINABLE filter #-}
+  {-# INLINE filter #-}
 
 #if (MIN_VERSION_base(4,7,0))
 instance Witherable Proxy where
@@ -145,10 +145,25 @@   wither f = fmap V.fromList . wither f . V.toList
   {-# INLINABLE wither #-}
   filter = V.filter
-  {-# INLINABLE filter #-}
+  {-# INLINE filter #-}
 
 instance Witherable S.Seq where
   wither f = fmap S.fromList . wither f . F.toList
   {-# INLINABLE wither #-}
   filter = S.filter
-  {-# INLINABLE filter #-}
+  {-# INLINE filter #-}
+
+-- | Traversable containers which hold 'Maybe' are witherable.
+newtype Chipped t a = Chipped { getChipped :: t (Maybe a) } deriving (Functor, F.Foldable, T.Traversable)
+
+deriving instance Show (t (Maybe a)) => Show (Chipped t a)
+deriving instance Read (t (Maybe a)) => Read (Chipped t a)
+deriving instance Eq (t (Maybe a)) => Eq (Chipped t a)
+deriving instance Ord (t (Maybe a)) => Ord (Chipped t a)
+
+instance Applicative t => Applicative (Chipped t) where
+  pure a = Chipped (pure (pure a))
+  Chipped f <*> Chipped t = Chipped (liftA2 (<*>) f t)
+
+instance T.Traversable t => Witherable (Chipped t) where
+  wither f = fmap Chipped . T.traverse (wither f) . getChipped
witherable.cabal view
@@ -1,5 +1,5 @@ name:                witherable
-version:             0.1.2.1
+version:             0.1.2.2
 synopsis:            Generalization of filter and catMaybes
 -- description:
 homepage:            https://github.com/fumieval/witherable