{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE CPP, DeriveFunctor, DeriveFoldable, DeriveTraversable, StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances, FlexibleContexts, GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE EmptyCase #-}
module Data.Witherable
( Filterable(..)
, (<$?>)
, (<&?>)
, Witherable(..)
, ordNub
, hashNub
, forMaybe
, FilterableWithIndex(..)
, WitherableWithIndex(..)
, WitherLike, Wither, WitherLike', Wither'
, FilterLike, Filter, FilterLike', Filter'
, witherOf
, forMaybeOf
, mapMaybeOf
, catMaybesOf
, filterAOf
, filterOf
, ordNubOf
, hashNubOf
, cloneFilter
, Peat(..)
, WrappedFoldable(..)
)
where
import qualified Control.Lens as Lens
import Data.Witherable.Class
import qualified Data.IntMap.Lazy as IM
import qualified Data.Map.Lazy as M
import qualified Data.Map.Monoidal as MM
import qualified Data.Sequence as S
import qualified Data.Vector as V
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 Data.Functor.Reverse (Reverse (..))
import Control.Applicative.Backwards (Backwards (..))
import Control.Monad.Trans.State.Strict
import Data.Monoid
import Data.Orphans ()
import Data.Proxy
import Data.Void
import Data.Coerce (coerce)
import Prelude hiding (filter)
type Filter s t a b = Wither s t a b
{-# DEPRECATED Filter "Use Wither instead" #-}
type FilterLike f s t a b = WitherLike f s t a b
{-# DEPRECATED FilterLike "Use WitherLike instead" #-}
type Filter' s a = Wither' s a
{-# DEPRECATED Filter' "Use Filter' instead" #-}
type FilterLike' f s a = WitherLike' f s a
{-# DEPRECATED FilterLike' "Use WitherLike' instead" #-}
type WitherLike f s t a b = (a -> f (Maybe b)) -> s -> f t
type Wither s t a b = forall f. Applicative f => WitherLike f s t a b
type WitherLike' f s a = WitherLike f s s a a
type Wither' s a = forall f. Applicative f => WitherLike' f s a
newtype Peat a b t = Peat { runPeat :: forall f. Applicative f => (a -> f (Maybe b)) -> f t }
instance Functor (Peat a b) where
fmap f (Peat k) = Peat (fmap f . k)
{-# INLINE fmap #-}
instance Applicative (Peat a b) where
pure a = Peat $ const (pure a)
{-# 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
cloneFilter :: FilterLike (Peat a b) s t a b -> Filter s t a b
cloneFilter l f = (`runPeat` f) . l (\a -> Peat $ \g -> g a)
{-# INLINABLE cloneFilter #-}
witherOf :: FilterLike f s t a b -> (a -> f (Maybe b)) -> s -> f t
witherOf = id
{-# INLINE witherOf #-}
forMaybeOf :: FilterLike f s t a b -> s -> (a -> f (Maybe b)) -> f t
forMaybeOf = flip
{-# INLINE forMaybeOf #-}
idDot :: (a -> b) -> a -> Identity b
idDot = coerce
mapMaybeOf :: FilterLike Identity s t a b -> (a -> Maybe b) -> s -> t
mapMaybeOf w f = runIdentity . w (idDot f)
{-# INLINE mapMaybeOf #-}
catMaybesOf :: FilterLike Identity s t (Maybe a) a -> s -> t
catMaybesOf w = mapMaybeOf w id
{-# INLINE catMaybesOf #-}
filterAOf :: Functor f => FilterLike' f s a -> (a -> f Bool) -> s -> f s
filterAOf w f = w $ \a -> (\b -> if b then Just a else Nothing) <$> f a
{-# INLINABLE filterAOf #-}
filterOf :: FilterLike' Identity s a -> (a -> Bool) -> s -> s
filterOf w f = runIdentity . filterAOf w (idDot f)
{-# INLINE filterOf #-}
(<$?>) :: Filterable f => (a -> Maybe b) -> f a -> f b
(<$?>) = mapMaybe
infixl 4 <$?>
(<&?>) :: Filterable f => f a -> (a -> Maybe b) -> f b
as <&?> f = mapMaybe f as
infixl 1 <&?>
class (Lens.FunctorWithIndex i t, Filterable t) => FilterableWithIndex i t | t -> i where
imapMaybe :: (i -> a -> Maybe b) -> t a -> t b
imapMaybe f = catMaybes . Lens.imap f
{-# INLINE imapMaybe #-}
ifilter :: (i -> a -> Bool) -> t a -> t a
ifilter f = imapMaybe $ \i a -> if f i a then Just a else Nothing
{-# INLINE ifilter #-}
forMaybe :: (Witherable t, Applicative f) => t a -> (a -> f (Maybe b)) -> f (t b)
forMaybe = flip wither
{-# INLINE forMaybe #-}
class (Lens.TraversableWithIndex i t, Witherable t) => WitherableWithIndex i t | t -> i where
iwither :: (Applicative f) => (i -> a -> f (Maybe b)) -> t a -> f (t b)
iwither f = fmap catMaybes . Lens.itraverse f
iwitherM :: (Monad m) => (i -> a -> m (Maybe b)) -> t a -> m (t b)
iwitherM = iwither
ifilterA :: (Applicative f) => (i -> a -> f Bool) -> t a -> f (t a)
ifilterA f = iwither (\i a -> (\b -> if b then Just a else Nothing) <$> f i a)
ordNubOf :: Ord a => FilterLike' (State (Set.Set a)) s a -> s -> s
ordNubOf w t = evalState (w f t) Set.empty
where
f a = state $ \s -> if Set.member a s
then (Nothing, s)
else (Just a, Set.insert a s)
{-# INLINE ordNubOf #-}
hashNubOf :: (Eq a, Hashable a) => FilterLike' (State (HSet.HashSet a)) s a -> s -> s
hashNubOf w t = evalState (w f t) HSet.empty
where
f a = state $ \s -> if HSet.member a s
then (Nothing, s)
else (Just a, HSet.insert a s)
{-# INLINE hashNubOf #-}
ordNub :: (Witherable t, Ord a) => t a -> t a
ordNub = ordNubOf witherM
{-# INLINE ordNub #-}
hashNub :: (Witherable t, Eq a, Hashable a) => t a -> t a
hashNub = hashNubOf witherM
{-# INLINE hashNub #-}
mapMaybeDefault :: (F.Foldable f, Alternative f) => (a -> Maybe b) -> f a -> f b
mapMaybeDefault p = F.foldr (\x xs -> case p x of
Just a -> pure a <|> xs
_ -> xs) empty
{-# INLINABLE mapMaybeDefault #-}
imapMaybeDefault :: (Lens.FoldableWithIndex i f, Alternative f) => (i -> a -> Maybe b) -> f a -> f b
imapMaybeDefault p = Lens.ifoldr (\i x xs -> case p i x of
Just a -> pure a <|> xs
_ -> xs) empty
{-# INLINABLE imapMaybeDefault #-}
newtype WrappedFoldable f a = WrapFilterable {unwrapFoldable :: f a}
deriving (Functor, F.Foldable, T.Traversable, Applicative, Alternative)
instance (Lens.FunctorWithIndex i f) => Lens.FunctorWithIndex i (WrappedFoldable f) where
imap f = WrapFilterable . Lens.imap f . unwrapFoldable
instance (Lens.FoldableWithIndex i f) => Lens.FoldableWithIndex i (WrappedFoldable f) where
ifoldMap f = Lens.ifoldMap f . unwrapFoldable
instance (Lens.TraversableWithIndex i f) => Lens.TraversableWithIndex i (WrappedFoldable f) where
itraverse f = fmap WrapFilterable . Lens.itraverse f . unwrapFoldable
instance (F.Foldable f, Alternative f) => Filterable (WrappedFoldable f) where
{-#INLINE mapMaybe#-}
mapMaybe = mapMaybeDefault
instance (Lens.FunctorWithIndex i f, Lens.FoldableWithIndex i f, Alternative f) => FilterableWithIndex i (WrappedFoldable f) where
{-# INLINE imapMaybe #-}
imapMaybe = imapMaybeDefault
instance FilterableWithIndex () Maybe
instance WitherableWithIndex () Maybe
instance FilterableWithIndex Int []
instance FilterableWithIndex Int ZipList
instance (Alternative f, T.Traversable f) => Witherable (WrappedFoldable f)
instance WitherableWithIndex Int []
instance WitherableWithIndex Int ZipList
instance FilterableWithIndex Int IM.IntMap where
imapMaybe = IM.mapMaybeWithKey
ifilter = IM.filterWithKey
instance WitherableWithIndex Int IM.IntMap where
instance FilterableWithIndex k (M.Map k) where
imapMaybe = M.mapMaybeWithKey
ifilter = M.filterWithKey
instance WitherableWithIndex k (M.Map k) where
#if MIN_VERSION_containers(0,5,8)
iwither = M.traverseMaybeWithKey
#endif
instance Filterable (MM.MonoidalMap k) where
mapMaybe = MM.mapMaybe
filter = MM.filter
instance Witherable (MM.MonoidalMap k)
instance FilterableWithIndex k (MM.MonoidalMap k) where
imapMaybe = MM.mapMaybeWithKey
ifilter = MM.filterWithKey
instance WitherableWithIndex k (MM.MonoidalMap k)
instance (Eq k, Hashable k) => FilterableWithIndex k (HM.HashMap k) where
imapMaybe = HM.mapMaybeWithKey
ifilter = HM.filterWithKey
instance (Eq k, Hashable k) => WitherableWithIndex k (HM.HashMap k) where
instance FilterableWithIndex Void Proxy
instance WitherableWithIndex Void Proxy
instance FilterableWithIndex Int V.Vector where
imapMaybe = V.imapMaybe
ifilter = V.ifilter
instance WitherableWithIndex Int V.Vector
instance FilterableWithIndex Int S.Seq
instance WitherableWithIndex Int S.Seq
instance (Lens.FunctorWithIndex i f, FilterableWithIndex j g) => FilterableWithIndex (i, j) (Compose f g) where
imapMaybe f = Compose . Lens.imap (\i -> imapMaybe (\j -> f (i, j))) . getCompose
ifilter p = Compose . Lens.imap (\i -> ifilter (\j -> p (i, j))) . getCompose
instance (Lens.TraversableWithIndex i f, WitherableWithIndex j g) => WitherableWithIndex (i, j) (Compose f g) where
iwither f = fmap Compose . Lens.itraverse (\i -> iwither (\j -> f (i, j))) . getCompose
iwitherM f = fmap Compose . Lens.imapM (\i -> iwitherM (\j -> f (i, j))) . getCompose
ifilterA p = fmap Compose . Lens.itraverse (\i -> ifilterA (\j -> p (i, j))) . getCompose
instance (FilterableWithIndex i f, FilterableWithIndex j g) => FilterableWithIndex (Either i j) (P.Product f g) where
imapMaybe f (P.Pair x y) = P.Pair (imapMaybe (f . Left) x) (imapMaybe (f . Right) y)
ifilter p (P.Pair x y) = P.Pair (ifilter (p . Left) x) (ifilter (p . Right) y)
instance (WitherableWithIndex i f, WitherableWithIndex j g) => WitherableWithIndex (Either i j) (P.Product f g) where
iwither f (P.Pair x y) = liftA2 P.Pair (iwither (f . Left) x) (iwither (f . Right) y)
iwitherM f (P.Pair x y) = liftA2 P.Pair (iwitherM (f . Left) x) (iwitherM (f . Right) y)
ifilterA p (P.Pair x y) = liftA2 P.Pair (ifilterA (p . Left) x) (ifilterA (p . Right) y)
instance (FilterableWithIndex i f, FilterableWithIndex j g) => FilterableWithIndex (Either i j) (Sum.Sum f g) where
imapMaybe f (Sum.InL x) = Sum.InL (imapMaybe (f . Left) x)
imapMaybe f (Sum.InR y) = Sum.InR (imapMaybe (f . Right) y)
ifilter f (Sum.InL x) = Sum.InL (ifilter (f . Left) x)
ifilter f (Sum.InR y) = Sum.InR (ifilter (f . Right) y)
instance (WitherableWithIndex i f, WitherableWithIndex j g) => WitherableWithIndex (Either i j) (Sum.Sum f g) where
iwither f (Sum.InL x) = Sum.InL <$> iwither (f . Left) x
iwither f (Sum.InR y) = Sum.InR <$> iwither (f . Right) y
iwitherM f (Sum.InL x) = Sum.InL <$> iwitherM (f . Left) x
iwitherM f (Sum.InR y) = Sum.InR <$> iwitherM (f . Right) y
ifilterA f (Sum.InL x) = Sum.InL <$> ifilterA (f . Left) x
ifilterA f (Sum.InR y) = Sum.InR <$> ifilterA (f . Right) y
deriving instance (FilterableWithIndex i f) => FilterableWithIndex i (IdentityT f)
instance (WitherableWithIndex i f) => WitherableWithIndex i (IdentityT f) where
iwither f (IdentityT m) = IdentityT <$> iwither f m
iwitherM f (IdentityT m) = IdentityT <$> iwitherM f m
ifilterA p (IdentityT m) = IdentityT <$> ifilterA p m
deriving instance FilterableWithIndex i t => FilterableWithIndex i (Reverse t)
instance WitherableWithIndex i t => WitherableWithIndex i (Reverse t) where
iwither f (Reverse t) = fmap Reverse . forwards $ iwither (\i -> Backwards . f i) t
ifilterA p (Reverse t) = fmap Reverse . forwards $ ifilterA (\i -> Backwards . p i) t
deriving instance FilterableWithIndex i t => FilterableWithIndex i (Backwards t)
instance WitherableWithIndex i t => WitherableWithIndex i (Backwards t) where
iwither f (Backwards xs) = Backwards <$> iwither f xs
iwitherM f (Backwards xs) = Backwards <$> iwitherM f xs
ifilterA f (Backwards xs) = Backwards <$> ifilterA f xs