List 0.2 → 0.3.0
raw patch · 3 files changed
+67/−9 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Control.Monad.ListT: data ListT m a
+ Control.Monad.ListT: ListT :: m (ListItem (ListT m) a) -> ListT m a
+ Control.Monad.ListT: newtype ListT m a
+ Control.Monad.ListT: runListT :: ListT m a -> m (ListItem (ListT m) a)
+ Data.List.Class: foldl1L :: (List l) => (a -> a -> a) -> l a -> ItemM l a
+ Data.List.Class: instance (Functor m) => Functor (ListItem m)
+ Data.List.Class: iterateM :: (List l) => (a -> ItemM l a) -> ItemM l a -> l a
+ Data.List.Class: listStateJoin :: (List l, List k, (ItemM l) ~ (StateT s (ItemM k))) => l a -> ItemM l (k a)
+ Data.List.Class: sortOn :: (Ord b) => (a -> b) -> [a] -> [a]
+ Data.List.Class: takeWhileM :: (List l) => (a -> ItemM l Bool) -> l a -> l a
Files
- List.cabal +1/−1
- src/Control/Monad/ListT.hs +1/−1
- src/Data/List/Class.hs +65/−7
List.cabal view
@@ -1,5 +1,5 @@ Name: List-Version: 0.2+Version: 0.3.0 Category: Control Synopsis: List monad transformer and class Description:
src/Control/Monad/ListT.hs view
@@ -19,7 +19,7 @@ -- > fmap reads . -- > joinM $ (repeat getLine :: ListT IO (IO String)) -module Control.Monad.ListT (ListT) where+module Control.Monad.ListT (ListT(..)) where import Data.List.Class (List(..), ListItem(..), foldrL)
src/Data/List/Class.hs view
@@ -11,18 +11,24 @@ takeWhile, genericTake, scanl, transpose, zip, zipWith, -- | Non standard List operations- foldrL, foldlL, toList, lengthL, lastL,+ foldrL, foldlL, foldl1L, toList, lengthL, lastL, merge2On, mergeOn, -- | Operations useful for monadic lists- execute, joinM,+ execute, joinM, iterateM, takeWhileM,+ -- | Operations for non-monadic lists+ sortOn, -- | Convert between List types- transformListMonad+ transformListMonad,+ listStateJoin ) where import Control.Monad (MonadPlus(..), liftM) import Control.Monad.Identity (Identity(..))+import Control.Monad.State (StateT(..), evalStateT, get) import Data.Function (fix)+import Data.List (sortBy) import Data.Maybe (fromJust)+import Data.Ord (comparing) import Prelude hiding ( filter, repeat, scanl, takeWhile, zip, zipWith) @@ -48,6 +54,10 @@ runList (x:xs) = Identity $ Cons x xs joinL = runIdentity +instance Functor m => Functor (ListItem m) where+ fmap _ Nil = Nil+ fmap func (Cons x xs) = Cons (func x) (fmap func xs)+ -- | foldr for 'List's. -- the result and 'right side' values are monadic actions. foldrL :: List l => (a -> ItemM l b -> ItemM l b) -> ItemM l b -> l a -> ItemM l b@@ -92,6 +102,12 @@ let v = step startVal x in v `seq` foldlL step v xs +foldl1L :: List l => (a -> a -> a) -> l a -> ItemM l a+foldl1L step list = do+ item <- runList list+ let Cons x xs = item+ foldlL step x xs+ scanl :: List l => (a -> b -> a) -> a -> l b -> l a scanl step startVal list = cons startVal . joinL $ do@@ -126,12 +142,17 @@ liftM (`cons` joinL rest) action takeWhile :: List l => (a -> Bool) -> l a -> l a-takeWhile cond =+takeWhile = takeWhileM . fmap return++takeWhileM :: List l => (a -> ItemM l Bool) -> l a -> l a+takeWhileM cond = joinL . foldrL step (return mzero) where- step x- | cond x = return . cons x . joinL- | otherwise = const (return mzero)+ step x rest = do+ b <- cond x+ if b+ then return . cons x . joinL $ rest+ else return mzero -- | An action to transform a 'List' to a list --@@ -227,4 +248,41 @@ (Cons x xs, Nil) -> cons x xs (Nil, Cons y ys) -> cons y ys (Nil, Nil) -> mzero++-- sorts require looking at the whole list+-- even before the consumption of the first result element,+-- so they make no sense for monadic lists+sortOn :: Ord b => (a -> b) -> [a] -> [a]+sortOn = sortBy . comparing++-- | Monadic version of iterate.+-- Can be used to produce trees given a children of node function.+--+-- > import Data.List.Tree (bfsLayers)+-- > take 3 $ bfsLayers (iterateM (\i -> [i*2, i*2+1]) [1] :: ListT [] Int)+-- > [[1],[2,3],[4,5,6,7]]+iterateM :: List l => (a -> ItemM l a) -> ItemM l a -> l a+iterateM step startM =+ joinL $ do+ start <- startM+ return . cons start+ . iterateM step+ . step $ start++-- | listStateJoin can transform a+-- @ListT (StateT s m) a@ to a @StateT s m (ListT m a)@.+--+-- When iterating a list, a state is already maintained and passed along+-- in the form of the location along the list.+-- This joins the inner @StateT s@ into the list.+-- The list will fork the state given to it and won't share its changes.+listStateJoin :: (List l, List k, ItemM l ~ StateT s (ItemM k))+ => l a -> ItemM l (k a)+listStateJoin list = do+ start <- get+ return . joinL . (`evalStateT` start) $ do+ item <- runList list+ case item of+ Nil -> return mzero+ Cons x xs -> liftM (cons x) (listStateJoin xs)