generator 0.5 → 0.5.1
raw patch · 6 files changed
+97/−70 lines, 6 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Control.Monad.DList: instance (Monad m) => List (DListT m) m
- Data.List.Class: instance (Monad m) => List (ListT m) m
- Data.List.Class: instance List [] Identity
- Data.List.Class: sequence :: (List l m) => l (m a) -> m (l a)
- Data.List.Class: sequence_ :: (List l m) => l (m a) -> m ()
- Data.List.Tree: instance (List l k, List k m) => Tree l k m
+ Control.Monad.DList: instance (Monad m) => List (DListT m)
+ Data.List.Class: instance (Monad m) => List (ListT m)
+ Data.List.Class: instance List []
+ Data.List.Class: joinM :: (List l) => l (ItemM l a) -> l a
+ Data.List.Tree: instance (List t, List (ItemM t)) => Tree t
- Control.Monad.Consumer: evalConsumerT :: (List l m) => ConsumerT v m a -> l v -> m a
+ Control.Monad.Consumer: evalConsumerT :: (List l) => ConsumerT v (ItemM l) a -> l v -> ItemM l a
- Data.List.Class: class (MonadPlus l, Monad m) => List l m | l -> m
+ Data.List.Class: class (MonadPlus l, Monad (ItemM l)) => List l where { type family ItemM l :: * -> *; { fromListT = convList toListT = convList foldrL consFunc nilFunc = foldrL consFunc nilFunc . toListT } }
- Data.List.Class: convList :: (List l m, List k m) => l a -> k a
+ Data.List.Class: convList :: ((ItemM l) ~ (ItemM k), List l, List k) => l a -> k a
- Data.List.Class: execute :: (List l m) => l a -> m ()
+ Data.List.Class: execute :: (List l) => l a -> ItemM l ()
- Data.List.Class: foldlL :: (List l m) => (a -> b -> a) -> a -> l b -> m a
+ Data.List.Class: foldlL :: (List l) => (a -> b -> a) -> a -> l b -> ItemM l a
- Data.List.Class: foldrL :: (List l m) => (a -> m b -> m b) -> m b -> l a -> m b
+ Data.List.Class: foldrL :: (List l) => (a -> ItemM l b -> ItemM l b) -> ItemM l b -> l a -> ItemM l b
- Data.List.Class: fromListT :: (List l m) => ListT m a -> l a
+ Data.List.Class: fromListT :: (List l) => ListT (ItemM l) a -> l a
- Data.List.Class: genericTake :: (Integral i, List l m) => i -> l a -> l a
+ Data.List.Class: genericTake :: (Integral i, List l) => i -> l a -> l a
- Data.List.Class: joinL :: (List l m) => m (l b) -> l b
+ Data.List.Class: joinL :: (List l) => ItemM l (l b) -> l b
- Data.List.Class: lastL :: (List l m) => l a -> m a
+ Data.List.Class: lastL :: (List l) => l a -> ItemM l a
- Data.List.Class: lengthL :: (Integral i, List l m) => l a -> m i
+ Data.List.Class: lengthL :: (Integral i, List l) => l a -> ItemM l i
- Data.List.Class: liftListMonad :: (MonadTrans t, Monad (t m), List l m) => l a -> ListT (t m) a
+ Data.List.Class: liftListMonad :: (MonadTrans t, Monad (t (ItemM l)), List l) => l a -> ListT (t (ItemM l)) a
- Data.List.Class: scanl :: (List l m) => (a -> b -> a) -> a -> l b -> l a
+ Data.List.Class: scanl :: (List l) => (a -> b -> a) -> a -> l b -> l a
- Data.List.Class: takeWhile :: (List l m) => (a -> Bool) -> l a -> l a
+ Data.List.Class: takeWhile :: (List l) => (a -> Bool) -> l a -> l a
- Data.List.Class: toList :: (List l m) => l a -> m [a]
+ Data.List.Class: toList :: (List l) => l a -> ItemM l [a]
- Data.List.Class: toListT :: (List l m) => l a -> ListT m a
+ Data.List.Class: toListT :: (List l) => l a -> ListT (ItemM l) a
- Data.List.Class: transformListMonad :: (List l m, List k s) => (forall x. m x -> s x) -> l a -> k a
+ Data.List.Class: transformListMonad :: (List l, List k) => (forall x. ItemM l x -> ItemM k x) -> l a -> k a
- Data.List.Class: transpose :: (List l m) => l (l a) -> l (l a)
+ Data.List.Class: transpose :: (List l) => l (l a) -> l (l a)
- Data.List.Class: zip :: (List l m) => l a -> l b -> l (a, b)
+ Data.List.Class: zip :: (List l) => l a -> l b -> l (a, b)
- Data.List.Class: zipWith :: (List l m) => (a -> b -> c) -> l a -> l b -> l c
+ Data.List.Class: zipWith :: (List l) => (a -> b -> c) -> l a -> l b -> l c
- Data.List.Tree: bestFirstSearchOn :: (Ord b, Tree l k m) => (a -> b) -> l a -> k a
+ Data.List.Tree: bestFirstSearchOn :: (Ord b, Tree t) => (a -> b) -> t a -> ItemM t a
- Data.List.Tree: bestFirstSearchSortedChildrenOn :: (Ord b, Tree l k m) => (a -> b) -> l a -> k a
+ Data.List.Tree: bestFirstSearchSortedChildrenOn :: (Ord b, Tree t) => (a -> b) -> t a -> ItemM t a
- Data.List.Tree: bfs :: (Tree l k m) => l a -> k a
+ Data.List.Tree: bfs :: (Tree t) => t a -> ItemM t a
- Data.List.Tree: bfsLayers :: (Tree l k m) => l a -> k (k a)
+ Data.List.Tree: bfsLayers :: (Tree t) => t a -> ItemM t (ItemM t a)
- Data.List.Tree: class (List l k, List k m) => Tree l k m
+ Data.List.Tree: class (List t, List (ItemM t)) => Tree t
- Data.List.Tree: dfs :: (List l m, MonadPlus m) => l a -> m a
+ Data.List.Tree: dfs :: (List l, MonadPlus (ItemM l)) => l a -> ItemM l a
- Data.List.Tree: prune :: (List l m, MonadPlus m) => (a -> Bool) -> l a -> l a
+ Data.List.Tree: prune :: (List l, MonadPlus (ItemM l)) => (a -> Bool) -> l a -> l a
Files
- generator.cabal +1/−8
- src/Control/Monad/Consumer.hs +2/−2
- src/Control/Monad/DList.hs +3/−2
- src/Control/Monad/ListT.hs +4/−6
- src/Data/List/Class.hs +41/−36
- src/Data/List/Tree.hs +46/−16
generator.cabal view
@@ -1,5 +1,5 @@ Name: generator-Version: 0.5+Version: 0.5.1 Category: Control Synopsis: A list monad transformer and related functions. Description:@@ -32,10 +32,3 @@ Data.List.Class, Data.List.Tree Ghc-Options: -O2 -Wall- Extensions: FlexibleContexts,- FlexibleInstances,- FunctionalDependencies,- MultiParamTypeClasses,- RankNTypes,- UndecidableInstances-
src/Control/Monad/Consumer.hs view
@@ -38,11 +38,11 @@ liftIO = lift . liftIO -- | Consume a 'ListT'-evalConsumerT :: List l m => ConsumerT v m a -> l v -> m a+evalConsumerT :: List l => ConsumerT v (ItemM l) a -> l v -> ItemM l a evalConsumerT (ConsumerT i) = evalStateT i . Just . toListT -- Consumer no longer has a producer left...-putNoProducer :: List l m => StateT (Maybe (l v)) m ()+putNoProducer :: List l => StateT (Maybe (l v)) (ItemM l) () putNoProducer = put Nothing -- | Consume/get the next value
src/Control/Monad/DList.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-} -- | A difference-list monad transformer / a monadic difference-list. --@@ -41,7 +41,8 @@ mzero = mempty mplus = mappend -instance Monad m => List (DListT m) m where+instance Monad m => List (DListT m) where+ type ItemM (DListT m) = m joinL action = DListT $ \rest -> joinL $ liftM (`runDListT` rest) action
src/Control/Monad/ListT.hs view
@@ -8,18 +8,16 @@ -- A program which reads numbers from the user and accumulates them. -- -- > import Control.Monad.ListT (ListT)--- > import Data.List.Class (joinL, repeat, scanl, sequence, sequence_, takeWhile)--- > import Prelude hiding (repeat, scanl, sequence, sequence_, takeWhile)+-- > import Data.List.Class (execute, joinM, repeat, scanl, takeWhile)+-- > import Prelude hiding (repeat, scanl, takeWhile) -- > -- > main =--- > sequence_ .--- > fmap print .+-- > execute . joinM . fmap print . -- > scanl (+) 0 . -- > fmap (fst . head) . -- > takeWhile (not . null) . -- > fmap reads .--- > joinL . sequence $--- > (repeat getLine :: ListT IO (IO String))+-- > joinM $ (repeat getLine :: ListT IO (IO String)) module Control.Monad.ListT ( ListItem(..), ListT(..), foldrListT
src/Data/List/Class.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE FlexibleInstances, FunctionalDependencies, MultiParamTypeClasses, RankNTypes, UndecidableInstances #-}+{-# LANGUAGE FlexibleContexts, RankNTypes, TypeFamilies #-} -- | The 'List' class and actions for lists @@ -9,10 +9,9 @@ cons, fromList, filter, repeat, -- | Standard list operations takeWhile, genericTake, scanl,- sequence, sequence_, transpose,- zip, zipWith,+ transpose, zip, zipWith, -- | Non standard List operations- foldlL, toList, execute, lengthL, lastL,+ foldlL, toList, execute, joinM, lengthL, lastL, -- | Convert between List types convList, transformListMonad, liftListMonad ) where@@ -23,37 +22,40 @@ import Control.Monad.Trans (MonadTrans(..)) import Data.Function (fix) import Prelude hiding (- filter, repeat, scanl, sequence, sequence_, takeWhile, zip, zipWith)+ filter, repeat, scanl, takeWhile, zip, zipWith) -- | A class for list types. -- Every list has an underlying monad.-class (MonadPlus l, Monad m) => List l m | l -> m where+class (MonadPlus l, Monad (ItemM l)) => List l where+ type ItemM l :: * -> * -- | Transform an action returning a list to the returned list -- -- > > joinL $ Identity "hello" -- > "hello"- joinL :: m (l b) -> l b+ joinL :: ItemM l (l b) -> l b -- | foldr for 'List's. -- the result and 'right side' values are monadic actions.- foldrL :: (a -> m b -> m b) -> m b -> l a -> m b+ foldrL :: (a -> ItemM l b -> ItemM l b) -> ItemM l b -> l a -> ItemM l b foldrL consFunc nilFunc = foldrL consFunc nilFunc . toListT -- | Convert to a 'ListT'. -- -- Can be done with a foldrL but included in type-class for efficiency.- toListT :: l a -> ListT m a+ toListT :: l a -> ListT (ItemM l) a toListT = convList -- | Convert from a 'ListT'. -- -- Can be done with a foldrL but included in type-class for efficiency.- fromListT :: ListT m a -> l a+ fromListT :: ListT (ItemM l) a -> l a fromListT = convList -instance List [] Identity where+instance List [] where+ type ItemM [] = Identity joinL = runIdentity foldrL = foldr toListT = fromList -instance Monad m => List (ListT m) m where+instance Monad m => List (ListT m) where+ type ItemM (ListT m) = m joinL = ListT . (>>= runListT) foldrL = foldrListT toListT = id@@ -73,7 +75,7 @@ fromList = foldr (mplus . return) mzero -- | Convert between lists with the same underlying monad-convList :: (List l m, List k m) => l a -> k a+convList :: (ItemM l ~ ItemM k, List l, List k) => l a -> k a convList = joinL . foldrL step (return mzero) where@@ -92,8 +94,9 @@ | otherwise = mzero -- for foldlL and scanl-foldlL' :: List l m =>- (a -> m c -> c) -> (a -> c) -> (a -> b -> a) -> a -> l b -> c+foldlL' :: List l =>+ (a -> (ItemM l) c -> c) -> (a -> c) ->+ (a -> b -> a) -> a -> l b -> c foldlL' joinVals atEnd step startVal = t startVal . foldrL astep (return atEnd) where@@ -101,19 +104,19 @@ t cur = joinVals cur . (`ap` return cur) -- | An action to do foldl for 'List's-foldlL :: List l m => (a -> b -> a) -> a -> l b -> m a+foldlL :: List l => (a -> b -> a) -> a -> l b -> ItemM l a foldlL step startVal = foldlL' (const join) id astep (return startVal) where astep rest x = liftM (`step` x) rest -scanl :: List l m => (a -> b -> a) -> a -> l b -> l a+scanl :: List l => (a -> b -> a) -> a -> l b -> l a scanl = foldlL' consJoin $ const mzero where consJoin cur = cons cur . joinL -genericTake :: (Integral i, List l m) => i -> l a -> l a+genericTake :: (Integral i, List l) => i -> l a -> l a genericTake count | count <= 0 = const mzero | otherwise = foldlL' joinStep (const mzero) next Nothing@@ -125,21 +128,22 @@ joinStep (Just (_, x)) = cons x . joinL -- | Execute the monadic actions in a 'List'-execute :: List l m => l a -> m ()+execute :: List l => l a -> ItemM l () execute = foldlL const () -sequence :: List l m => l (m a) -> m (l a)-sequence =- foldrL consFunc (return mzero)+-- | Transform a list of actions to a list of their results+--+-- > > joinM [Identity 4, Identity 7]+-- > [4,7]+joinM :: List l => l (ItemM l a) -> l a+joinM =+ joinL . foldrL consFunc (return mzero) where consFunc action rest = do x <- action return . cons x . joinL $ rest -sequence_ :: List l m => l (m a) -> m ()-sequence_ = execute . joinL . sequence--takeWhile :: List l m => (a -> Bool) -> l a -> l a+takeWhile :: List l => (a -> Bool) -> l a -> l a takeWhile cond = joinL . foldrL step (return mzero) where@@ -151,7 +155,7 @@ -- -- > > runIdentity $ toList "hello!" -- > "hello!"-toList :: List l m => l a -> m [a]+toList :: List l => l a -> ItemM l [a] toList = foldrL step $ return [] where@@ -161,7 +165,7 @@ -- -- > > runIdentity $ lengthL [1,2,3] -- > 3-lengthL :: (Integral i, List l m) => l a -> m i+lengthL :: (Integral i, List l) => l a -> ItemM l i lengthL = foldlL (const . (+ 1)) 0 -- | Transform the underlying monad of a list given a way to transform the monad@@ -169,8 +173,8 @@ -- > > import Data.List.Tree (bfs) -- > > bfs (transformListMonad (\(Identity x) -> [x, x]) "hey" :: ListT [] Char) -- > "hheeeeyyyyyyyy"-transformListMonad :: (List l m, List k s) =>- (forall x. m x -> s x) -> l a -> k a+transformListMonad :: (List l, List k) =>+ (forall x. ItemM l x -> ItemM k x) -> l a -> k a transformListMonad trans = t . foldrL step (return mzero) where@@ -182,11 +186,11 @@ -- Doing plain 'transformListMonad lift' instead doesn't give the compiler -- the same knowledge about the types. liftListMonad ::- (MonadTrans t, Monad (t m), List l m) =>- l a -> ListT (t m) a+ (MonadTrans t, Monad (t (ItemM l)), List l) =>+ l a -> ListT (t (ItemM l)) a liftListMonad = transformListMonad lift -zip :: List l m => l a -> l b -> l (a, b)+zip :: List l => l a -> l b -> l (a, b) zip as bs = r0 (toListT as) (toListT bs) where@@ -196,6 +200,7 @@ case xi of Nil -> return mzero Cons x xs -> r1 x xs yy+ r1 :: List l => a -> ListT (ItemM l) a -> ListT (ItemM l) b -> ItemM l (l (a, b)) r1 x xs yy = do yi <- runListT yy return $ case yi of@@ -205,20 +210,20 @@ -- zipWith based on zip and not vice versa, -- because the other way around hlint compains "use zip".-zipWith :: List l m => (a -> b -> c) -> l a -> l b -> l c+zipWith :: List l => (a -> b -> c) -> l a -> l b -> l c zipWith func as = liftM (uncurry func) . zip as -- | Consume all items and return the last one -- -- > > runIdentity $ lastL "hello" -- > 'o'-lastL :: List l m => l a -> m a+lastL :: List l => l a -> ItemM l a lastL = foldlL (const id) undefined repeat :: MonadPlus m => a -> m a repeat = fix . cons -transpose :: List l m => l (l a) -> l (l a)+transpose :: List l => l (l a) -> l (l a) transpose matrix = joinL $ toList matrix >>= r . map toListT where
src/Data/List/Tree.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleContexts, FlexibleInstances, ScopedTypeVariables, UndecidableInstances #-} -- | Functions for iterating trees. -- A 'List' whose underlying monad is also a 'List' is a tree.@@ -48,42 +48,44 @@ import Control.Monad (MonadPlus(..), guard, join, liftM) import Control.Monad.ListT (ListT(..), ListItem(..)) import Data.List.Class (- List(..), cons, foldlL, sequence,+ List(..), cons, foldlL, joinM, transformListMonad, transpose)-import Prelude hiding (sequence) -- | A 'type-class synonym' for Trees.-class (List l k, List k m) => Tree l k m-instance (List l k, List k m) => Tree l k m+class (List t, List (ItemM t)) => Tree t+instance (List t, List (ItemM t)) => Tree t -search :: (List l m, MonadPlus m) => (m (m a) -> m a) -> l a -> m a+search :: (List l, MonadPlus (ItemM l)) => (ItemM l (ItemM l a) -> ItemM l a) -> l a -> ItemM l a search merge = merge . foldrL step mzero where step a = return . cons a . merge -- | Iterate a tree in DFS pre-order. (Depth First Search)-dfs :: (List l m, MonadPlus m) => l a -> m a+dfs :: (List l, MonadPlus (ItemM l)) => l a -> ItemM l a dfs = search join -toListTree :: Tree l k m => l a -> ListT (ListT m) a+toListTree :: Tree t => t a -> ListT (ListT (ItemM (ItemM t))) a toListTree = transformListMonad toListT -- | Transform a tree into lists of the items in its different layers-bfsLayers :: Tree l k m => l a -> k (k a)+bfsLayers :: Tree t => t a -> ItemM t (ItemM t a) bfsLayers = fromListT . liftM fromListT . search (liftM join . transpose) . liftM return . toListTree -- | Iterate a tree in BFS order. (Breadth First Search)-bfs :: Tree l k m => l a -> k a+bfs :: Tree t => t a -> ItemM t a bfs = join . bfsLayers -mergeOn :: (Ord b, Monad m) => (a -> b) -> ListT m (ListT m a) -> ListT m a+mergeOn ::+ forall a b m. (Ord b, Monad m) =>+ (a -> b) -> ListT m (ListT m a) -> ListT m a mergeOn f = joinL . foldlL merge2 mzero where+ merge2 :: ListT m a -> ListT m a -> ListT m a merge2 xx yy = joinL $ do xi <- runListT xx@@ -98,12 +100,13 @@ -- | Best First Search given a scoring function. bestFirstSearchOn ::- (Ord b, Tree l k m) => (a -> b) -> l a -> k a+ (Ord b, Tree t) => (a -> b) -> t a -> ItemM t a bestFirstSearchOn func = fromListT . search (mergeOn func) . toListTree mergeOnSortedHeads ::- (Ord b, Monad m) => (a -> b) -> ListT m (ListT m a) -> ListT m a+ forall a b m. (Ord b, Monad m) =>+ (a -> b) -> ListT m (ListT m a) -> ListT m a mergeOnSortedHeads f list = joinL $ do item <- runListT list@@ -116,6 +119,7 @@ Cons x xs -> cons x . mergeOnSortedHeads f $ bury xs yys where+ bury :: ListT m a -> ListT m (ListT m a) -> ListT m (ListT m a) bury xx yyy = joinL $ do xi <- runListT xx@@ -136,17 +140,43 @@ -- | Best-First-Search given that a node's children are in sorted order (best first) and given a scoring function. -- Especially useful for trees where nodes have an infinite amount of children, where 'bestFirstSearchOn' will get stuck.+--+-- Example: Find smallest Pythagorian Triplets+--+-- > import Control.Monad+-- > import Control.Monad.Generator+-- > import Control.Monad.Trans+-- > import Data.List.Tree+-- > import Data.Maybe+-- >+-- > pythagorianTriplets =+-- > catMaybes .+-- > fmap fst .+-- > bestFirstSearchSortedChildrenOn snd .+-- > generate $ do+-- > x <- lift [1..]+-- > yield (Nothing, x)+-- > y <- lift [1..]+-- > yield (Nothing, x + y)+-- > z <- lift [1..]+-- > yield (Nothing, x + y + z)+-- > lift . guard $ x^2 + y^2 == z^2+-- > yield (Just (x, y, z), 0)+-- >+-- > > print $ take 10 pythagorianTriplets+-- > [(3,4,5),(4,3,5),(6,8,10),(8,6,10),(5,12,13),(12,5,13),(9,12,15),(12,9,15),(15,8,17),(8,15,17)]+ bestFirstSearchSortedChildrenOn ::- (Ord b, Tree l k m) => (a -> b) -> l a -> k a+ (Ord b, Tree t) => (a -> b) -> t a -> ItemM t a bestFirstSearchSortedChildrenOn func = fromListT . search (mergeOnSortedHeads func) . toListTree -- | Prune a tree or list given a predicate. -- Unlike 'takeWhile' which stops a branch where the condition doesn't hold, -- prune "cuts" the whole branch (the underlying MonadPlus's mzero).-prune :: (List l m, MonadPlus m) => (a -> Bool) -> l a -> l a+prune :: (List l, MonadPlus (ItemM l)) => (a -> Bool) -> l a -> l a prune cond =- joinL . sequence . liftM r+ joinM . liftM r where r x = do guard $ cond x