packages feed

constrictor 0.1.1.0 → 0.1.1.1

raw patch · 2 files changed

+121/−52 lines, 2 filesdep +ghc-primdep ~basePVP: minor bump suggested

API additions: PVP suggests at least a minor version bump

Dependencies added: ghc-prim

Dependency ranges changed: base

API changes (from Hackage documentation)

+ Constrictor: traverse'' :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)

Files

constrictor.cabal view
@@ -1,7 +1,7 @@ name:   constrictor version:-  0.1.1.0+  0.1.1.1 synopsis:   strict versions of many things in base description:@@ -34,7 +34,8 @@   exposed-modules:     Constrictor    build-depends:-      base >=4.7 && < 5.0+      base >=4.5 && < 5.0+    , ghc-prim     , transformers    default-language:     Haskell2010
src/Constrictor.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP                        #-}+{-# LANGUAGE BangPatterns               #-} {-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveFunctor              #-} {-# LANGUAGE DeriveGeneric              #-}@@ -11,11 +12,16 @@ functions in base, as well as a few functions that do not have lazy versions that exist in base (see the section on Folds).++Many functions in this library have an increased+constraint from Functor/Applicative to Monad in+order to achieve strictness in their arguments+and/or result. -}  module Constrictor   ( -    -- * Strict monadic functions +    -- * Strict 'lift-like' functions      (<$!>)   , fmap'   , liftM'@@ -24,9 +30,8 @@   , liftM4'   , liftM5'   , ap' -    -    -- * Strict traversable functions   , traverse'+  , traverse''   , mapM'          -- * Folds@@ -47,31 +52,51 @@   , Ap(..)   ) where +import Prelude hiding (foldr,foldl)+ import Control.Applicative import Control.Monad (MonadPlus)+#if MIN_VERSION_base(4,9,0) import Control.Monad.Fail (MonadFail)+#endif import Control.Monad.Fix  (MonadFix)-import Control.Monad.Trans.Cont (evalCont, cont)+import Control.Monad.Trans.Cont (ContT(..), cont) import Data.Foldable import Data.Functor.Compose (Compose(..))+import Data.Functor.Identity (runIdentity) import Data.Monoid hiding ((<>))+#if MIN_VERSION_base(4,9,0) import Data.Semigroup-import Data.Traversable (traverse)+#endif+import Data.Traversable (traverse,Traversable) import GHC.Generics (Generic,Generic1) +#if !(MIN_VERSION_base(4,8,0))+import Control.Applicative (WrappedMonad(..))+#endif+ -- | A wrapped applicative functor. --   Please note that base 4.12.0.0 will include this type, --   and it will be removed from this library at that point. newtype Ap f a = Ap { getAp :: f a }   deriving ( Alternative, Applicative            , Enum, Eq, Foldable, Functor-           , Generic, Generic1-           , Monad, MonadFail, MonadFix, MonadPlus+           , Generic+#if MIN_VERSION_base(4,6,0)+           , Generic1+#endif+           , Monad+#if MIN_VERSION_base(4,9,0)+           , MonadFail+#endif+           , MonadFix, MonadPlus            , Num, Ord, Read, Show, Traversable            ) +#if MIN_VERSION_base(4,9,0) instance (Applicative f, Semigroup a) => Semigroup (Ap f a) where   (Ap x) <> (Ap y) = Ap $ liftA2 (<>) x y+#endif  instance (Applicative f, Monoid a) => Monoid (Ap f a) where   mempty = Ap $ pure mempty@@ -82,57 +107,81 @@ -- | Lazy in the monoidal accumulator. Monoidal accumulation --   happens from left to right. foldlMapA :: forall t b a f. (Foldable t, Monoid b, Applicative f) => (a -> f b) -> t a -> f b-foldlMapA f = foldr f' (pure mempty)-  where-    f' :: a -> f b -> f b-    f' x y = liftA2 mappend (f x) y+foldlMapA f = foldr (\x y -> liftA2 mappend (f x) y) (pure mempty)  -- | Lazy in the monoidal accumulator. Monoidal accumulation --   happens from left to right. foldrMapA :: forall t b a f. (Foldable t, Monoid b, Applicative f) => (a -> f b) -> t a -> f b-foldrMapA f = foldl f' (pure mempty)-  where-    f' :: f b -> a -> f b-    f' y x = liftA2 (flip mappend) (f x) y+foldrMapA f = foldl (\y x -> liftA2 (flip mappend) (f x) y) (pure mempty)  -- | Strict in the monoidal accumulator. --   For monads strict in the left argument of bind, --   this will run in constant space. --   Monoidal accumulation happens from left to right. foldlMapM' :: forall t b a m. (Foldable t, Monoid b, Monad m) => (a -> m b) -> t a -> m b-foldlMapM' f xs = foldr f' pure xs mempty+foldlMapM' f xs = foldr f' return xs mempty   where   f' :: a -> (b -> m b) -> b -> m b   f' x k bl = do-    br <- f x+    !br <- f x     k $! (mappend bl br)   -- Strict in the monoidal accumulator.  -- Monoidal accumulation happens from left to right. foldrMapM' :: forall t b a m. (Foldable t, Monoid b, Monad m) => (a -> m b) -> t a -> m b-foldrMapM' f xs = foldl f' pure xs mempty+foldrMapM' f xs = foldl f' return xs mempty   where   f' :: (b -> m b) -> a -> b -> m b   f' k x br = do-    bl <- f x+    !bl <- f x     k $! (mappend bl br)   infixl 4 <$!>, `fmap'`, `liftM'` --- | Strict version of 'Data.Functor.<$>'+-- | This is 'Data.Functor.<$>', but strict in its+-- argument and result.+--+-- This is re-defined in this module, and not+-- just re-exported from @'Control.Monad'@.+-- The reason for this is that there is no way+-- to hide the docs for re-exports with Haddocks.+--+-- In the common case that one might import+-- @'Control.Monad'@, we recommend structuring+-- imports like so:+--+-- @+-- import Control.Monad hiding ((<$!>))+-- import Constrictor+-- @+--+-- or+--+-- @+-- import Control.Monad+-- import Constrictor hiding ((<$!>))+-- @+--+-- There should be no side effects (i.e.+-- naming/scoping conflicts) introduced as a+-- result of structuring one's imports in this way. (<$!>) :: Monad m => (a -> b) -> m a -> m b {-# INLINE (<$!>) #-} f <$!> m = do-  x <- m-  pure $! f x+  !x <- m+  return $! f x +-- | This is 'Data.Functor.fmap', but strict in its+-- argument and result.+-- -- Note this is equivalent to '<$!>', -- and is provided for convenience. fmap' :: Monad m => (a -> b) -> m a -> m b {-# INLINE fmap' #-} fmap' = (<$!>) --- | Strict version of 'Control.Monad.liftM'.+-- | This is 'Control.Monad.liftM', but strict in its+-- argument and result. -- -- Note this is equivalent to '<$!>', -- and is provided for convenience.@@ -140,63 +189,82 @@ {-# INLINE liftM' #-}  liftM' = (<$!>) --- | Strict version of 'Control.Monad.liftM2'.+-- | This is 'Control.Monad.liftM2', but strict in its+-- arguments and result. liftM2' :: Monad m => (a -> b -> c) -> m a -> m b -> m c {-# INLINE liftM2' #-} liftM2' f a b = do-  x <- a-  y <- b-  pure $! f x y+  !x <- a+  !y <- b+  return $! f x y --- | Strict version of 'Control.Monad.liftM3'.+-- | This is 'Control.Monad.liftM3', but strict in its+-- arguments and result. liftM3' :: Monad m => (a -> b -> c -> d) -> m a -> m b -> m c -> m d {-# INLINE liftM3' #-} liftM3' f a b c = do-  x <- a-  y <- b-  z <- c-  pure $! f x y z+  !x <- a+  !y <- b+  !z <- c+  return $! f x y z --- | Strict version of 'Control.Monad.liftM4'.+-- | This is 'Control.Monad.liftM4', but strict in its+-- arguments and result. liftM4' :: Monad m => (a -> b -> c -> d -> e) -> m a -> m b -> m c -> m d -> m e  {-# INLINE liftM4' #-} liftM4' f a b c d = do-  x <- a-  y <- b-  z <- c-  u <- d-  pure $! f x y z u+  !x <- a+  !y <- b+  !z <- c+  !u <- d+  return $! f x y z u --- | Strict version of 'Control.Monad.liftM5'.+-- | This is 'Control.Monad.liftM5', but strict in its+-- arguments and result. liftM5' :: Monad m => (a -> b -> c -> d -> e -> f) -> m a -> m b -> m c -> m d -> m e -> m f {-# INLINE liftM5' #-} liftM5' f a b c d e = do-  x <- a-  y <- b-  z <- c-  u <- d-  v <- e-  pure $! f x y z u v+  !x <- a+  !y <- b+  !z <- c+  !u <- d+  !v <- e+  return $! f x y z u v --- | Strict version of 'Control.Monad.ap'+-- | This is 'Control.Monad.ap', but strict in its+-- arguments and result. ap' :: Monad m => m (a -> b) -> m a -> m b {-# INLINE ap' #-} ap' m1 m2 = do-  f <- m1-  x <- m2-  pure $! f x+  !f <- m1+  !x <- m2+  return $! f x  -- | Strict version of 'Data.Traversable.traverse'. traverse' :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b) {-# INLINE traverse' #-}-traverse' f = fmap evalCont . getCompose . traverse (Compose . fmap (\a -> cont $ \k -> k $! a) . f)+traverse' f = fmap (runIdentity . evalContT) . getCompose . traverse (Compose . fmap (\a -> cont $ \k -> k $! a) . f) +-- | Stricter version of 'Data.Traversable.traverse'.+traverse'' :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)+{-# INLINE traverse'' #-}+traverse'' f = fmap' (runIdentity . evalContT) . getCompose . traverse (Compose . fmap' (\a -> cont $ \k -> k $! a) . f)++-- this is copied from transformers for backwards compatibility+evalContT :: (Monad m) => ContT r m r -> m r+evalContT m = runContT m return+{-# INLINE evalContT #-}+ -- | Strict version of 'Control.Monad.mapM'. -- -- This is just 'traverse'' specialised to 'Monad'. mapM' :: (Traversable t, Monad m) => (a -> m b) -> t a-> m (t b) {-# INLINE mapM' #-}+#if MIN_VERSION_base(4,8,0) mapM' = traverse'+#else+mapM' f xs = unwrapMonad (traverse' (\x -> WrapMonad (f x)) xs)+#endif  -- The INLINES used below allow more list functions to fuse. -- See Trac #9848.