list-transformer 1.0.0 → 1.0.1
raw patch · 3 files changed
+104/−5 lines, 3 filesdep +doctestdep +list-transformerdep ~basePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: doctest, list-transformer
Dependency ranges changed: base
API changes (from Hackage documentation)
- List.Transformer: instance (Monad m, Floating a) => Floating (ListT m a)
- List.Transformer: instance (Monad m, Fractional a) => Fractional (ListT m a)
- List.Transformer: instance (Monad m, Monoid a) => Monoid (ListT m a)
- List.Transformer: instance (Monad m, Num a) => Num (ListT m a)
- List.Transformer: instance (Monad m, Traversable m) => Traversable (ListT m)
- List.Transformer: instance (Monad m, Traversable m) => Traversable (Step m)
- List.Transformer: instance Foldable m => Foldable (ListT m)
- List.Transformer: instance Foldable m => Foldable (Step m)
- List.Transformer: instance Monad m => Alternative (ListT m)
- List.Transformer: instance Monad m => Applicative (ListT m)
- List.Transformer: instance Monad m => Functor (ListT m)
- List.Transformer: instance Monad m => Functor (Step m)
- List.Transformer: instance Monad m => Monad (ListT m)
- List.Transformer: instance Monad m => MonadPlus (ListT m)
- List.Transformer: instance MonadError e m => MonadError e (ListT m)
- List.Transformer: instance MonadIO m => MonadIO (ListT m)
- List.Transformer: instance MonadReader i m => MonadReader i (ListT m)
- List.Transformer: instance MonadState s m => MonadState s (ListT m)
- List.Transformer: instance MonadTrans ListT
- List.Transformer: next :: ListT m a -> m (Step m a)
+ List.Transformer: [next] :: ListT m a -> m (Step m a)
+ List.Transformer: drop :: Monad m => Int -> ListT m a -> ListT m a
+ List.Transformer: instance (GHC.Base.Monad m, Data.Traversable.Traversable m) => Data.Traversable.Traversable (List.Transformer.ListT m)
+ List.Transformer: instance (GHC.Base.Monad m, Data.Traversable.Traversable m) => Data.Traversable.Traversable (List.Transformer.Step m)
+ List.Transformer: instance (GHC.Base.Monad m, GHC.Base.Monoid a) => GHC.Base.Monoid (List.Transformer.ListT m a)
+ List.Transformer: instance (GHC.Base.Monad m, GHC.Float.Floating a) => GHC.Float.Floating (List.Transformer.ListT m a)
+ List.Transformer: instance (GHC.Base.Monad m, GHC.Num.Num a) => GHC.Num.Num (List.Transformer.ListT m a)
+ List.Transformer: instance (GHC.Base.Monad m, GHC.Real.Fractional a) => GHC.Real.Fractional (List.Transformer.ListT m a)
+ List.Transformer: instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (List.Transformer.ListT m)
+ List.Transformer: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (List.Transformer.ListT m)
+ List.Transformer: instance Control.Monad.Reader.Class.MonadReader i m => Control.Monad.Reader.Class.MonadReader i (List.Transformer.ListT m)
+ List.Transformer: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (List.Transformer.ListT m)
+ List.Transformer: instance Control.Monad.Trans.Class.MonadTrans List.Transformer.ListT
+ List.Transformer: instance Data.Foldable.Foldable m => Data.Foldable.Foldable (List.Transformer.ListT m)
+ List.Transformer: instance Data.Foldable.Foldable m => Data.Foldable.Foldable (List.Transformer.Step m)
+ List.Transformer: instance GHC.Base.Monad m => GHC.Base.Alternative (List.Transformer.ListT m)
+ List.Transformer: instance GHC.Base.Monad m => GHC.Base.Applicative (List.Transformer.ListT m)
+ List.Transformer: instance GHC.Base.Monad m => GHC.Base.Functor (List.Transformer.ListT m)
+ List.Transformer: instance GHC.Base.Monad m => GHC.Base.Functor (List.Transformer.Step m)
+ List.Transformer: instance GHC.Base.Monad m => GHC.Base.Monad (List.Transformer.ListT m)
+ List.Transformer: instance GHC.Base.Monad m => GHC.Base.MonadPlus (List.Transformer.ListT m)
+ List.Transformer: take :: Monad m => Int -> ListT m a -> ListT m a
+ List.Transformer: unfold :: Monad m => (b -> m (Maybe (a, b))) -> b -> ListT m a
+ List.Transformer: zip :: Monad m => ListT m a -> ListT m b -> ListT m (a, b)
- List.Transformer: (<|>) :: Alternative f => f a -> f a -> f a
+ List.Transformer: (<|>) :: f a -> f a -> f a
- List.Transformer: empty :: Alternative f => f a
+ List.Transformer: empty :: f a
- List.Transformer: lift :: (MonadTrans t, Monad m) => m a -> t m a
+ List.Transformer: lift :: Monad m => m a -> t m a
- List.Transformer: liftIO :: MonadIO m => IO a -> m a
+ List.Transformer: liftIO :: IO a -> m a
- List.Transformer: many :: Alternative f => f a -> f [a]
+ List.Transformer: many :: f a -> f [a]
- List.Transformer: some :: Alternative f => f a -> f [a]
+ List.Transformer: some :: f a -> f [a]
Files
- list-transformer.cabal +11/−1
- src/List/Transformer.hs +84/−4
- test/DocTest.hs +9/−0
list-transformer.cabal view
@@ -1,5 +1,5 @@ name: list-transformer-version: 1.0.0+version: 1.0.1 synopsis: List monad transformer description: This library provides a list monad transformer that enriches lists with effects and streams efficiently in@@ -25,3 +25,13 @@ build-depends: base >= 4.5 && < 5 , mtl >= 2.1 && < 2.3 ghc-options: -Wall++test-suite doctest+ type: exitcode-stdio-1.0+ main-is: DocTest.hs+ hs-source-dirs: test+ build-depends:+ base+ , doctest+ , list-transformer+ default-language: Haskell2010
src/List/Transformer.hs view
@@ -11,8 +11,8 @@ > -- Every `ListT` begins with an outermost effect (the `m`) > newtype ListT m a = ListT { next :: m (Step m a) }-> >+> > -- The return value of that effect is either > -- * Cons: a new list element followed by the rest of the list > -- * Nil : an empty list@@ -48,7 +48,7 @@ Combining @stdin@ and @stdout@ forwards lines one-by-one from standard input to standard output:- + > main :: IO () > main = stdout stdin @@ -79,7 +79,7 @@ You can even use list comprehension syntax if you enable the @MonadComprehensions@ language extension: -> stdout strings = runListT [ r | string <- strings, r <- liftIO (putStrLn str) ]+> stdout strings = runListT [ r | str <- strings, r <- liftIO (putStrLn str) ] The most important operations that you should familiarize yourself with are: @@ -103,7 +103,7 @@ > (>>=) :: ListT IO a -> (a -> ListT IO b) -> ListT IO b - For example, suppose you want to a build a `ListT` with three elements and+ For example, suppose you want to build a `ListT` with three elements and no effects. You could just write: > pure 1 <|> pure 2 <|> pure 3 :: ListT IO Int@@ -175,6 +175,10 @@ , fold , foldM , select+ , take+ , drop+ , unfold+ , zip -- * Step , Step(..)@@ -199,9 +203,13 @@ import Control.Monad.State.Class (MonadState(..)) import Control.Monad.Reader.Class (MonadReader(..)) import Control.Monad.Trans (MonadTrans(..), MonadIO(..))+import Prelude hiding (drop, take, zip) import qualified Data.Foldable +-- $setup+-- >>> :set -XNoMonomorphismRestriction+ {-| This is like a list except that you can interleave effects between each list element. For example: @@ -419,6 +427,78 @@ select = Data.Foldable.foldr cons empty where cons x xs = pure x <|> xs+++-- | @take n xs@ takes @n@ elements from the head of @xs@.+--+-- >>> let list xs = do x <- select xs; liftIO (print (show x)); return x+-- >>> let sum = fold (+) 0 id+-- >>> sum (take 2 (list [5,4,3,2,1]))+-- "5"+-- "4"+-- 9+take :: Monad m => Int -> ListT m a -> ListT m a+take n l+ | n <= 0 = empty+ | otherwise = ListT (do+ s <- next l+ case s of+ Cons a l' -> return (Cons a (take (n-1) l'))+ Nil -> return Nil)++-- | @drop n xs@ drops @n@ elements from the head of @xs@, but still runs their+-- effects.+--+-- >>> let list xs = do x <- select xs; liftIO (print (show x)); return x+-- >>> let sum = fold (+) 0 id+-- >>> sum (drop 2 (list [5,4,3,2,1]))+-- "5"+-- "4"+-- "3"+-- "2"+-- "1"+-- 6+drop :: Monad m => Int -> ListT m a -> ListT m a+drop n l+ | n <= 0 = l+ | otherwise = ListT (do+ s <- next l+ case s of+ Cons _ l' -> next (drop (n-1) l')+ Nil -> return Nil)++-- | @unfold step seed@ generates a 'ListT' from a @step@ function and an+-- initial @seed@.+unfold :: Monad m => (b -> m (Maybe (a, b))) -> b -> ListT m a+unfold step = loop+ where+ loop seed = ListT (do+ mx <- step seed+ case mx of+ Just (x, seed') -> return (Cons x (loop seed'))+ Nothing -> return Nil)++-- | @zip xs ys@ zips two 'ListT' together, running the effects of each before+-- possibly recursing. Notice in the example below, @4@ is output even though+-- it has no corresponding element in the second list.+--+-- >>> let list xs = do x <- select xs; liftIO (print (show x)); return x+-- >>> runListT (zip (list [1,2,3,4,5]) (list [6,7,8]))+-- "1"+-- "6"+-- "2"+-- "7"+-- "3"+-- "8"+-- "4"+zip :: Monad m => ListT m a -> ListT m b -> ListT m (a, b)+zip xs ys = ListT (do+ sx <- next xs+ sy <- next ys+ case (sx, sy) of+ (Cons x xs', Cons y ys') -> return (Cons (x, y) (zip xs' ys'))+ _ -> return Nil)+ {-| Pattern match on this type when you loop explicitly over a `ListT` using `next`. For example:
+ test/DocTest.hs view
@@ -0,0 +1,9 @@+module Main where++import Test.DocTest++main :: IO ()+main = doctest+ [ "-XCPP"+ , "src/List/Transformer.hs"+ ]