packages feed

generator 0.5.1 → 0.5.2

raw patch · 4 files changed

+6/−549 lines, 4 filesdep +ListPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: List

API changes (from Hackage documentation)

- Control.Monad.ListT: Cons :: a -> l a -> ListItem l a
- Control.Monad.ListT: ListT :: m (ListItem (ListT m) a) -> ListT m a
- Control.Monad.ListT: Nil :: ListItem l a
- Control.Monad.ListT: data ListItem l a
- Control.Monad.ListT: data ListT m a
- Control.Monad.ListT: foldrListT :: (Monad m) => (a -> m b -> m b) -> m b -> ListT m a -> m b
- Control.Monad.ListT: headL :: ListItem l a -> a
- Control.Monad.ListT: instance (Monad m) => Applicative (ListT m)
- Control.Monad.ListT: instance (Monad m) => Functor (ListT m)
- Control.Monad.ListT: instance (Monad m) => Monad (ListT m)
- Control.Monad.ListT: instance (Monad m) => MonadPlus (ListT m)
- Control.Monad.ListT: instance (Monad m) => Monoid (ListT m a)
- Control.Monad.ListT: instance (MonadError e m) => MonadError e (ListT m)
- Control.Monad.ListT: instance (MonadIO m) => MonadIO (ListT m)
- Control.Monad.ListT: instance (MonadReader s m) => MonadReader s (ListT m)
- Control.Monad.ListT: instance (MonadState s m) => MonadState s (ListT m)
- Control.Monad.ListT: instance MonadTrans ListT
- Control.Monad.ListT: runListT :: ListT m a -> m (ListItem (ListT m) a)
- Control.Monad.ListT: tailL :: ListItem l a -> l a
- 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: cons :: (MonadPlus m) => a -> m a -> m a
- Data.List.Class: convList :: ((ItemM l) ~ (ItemM k), List l, List k) => l a -> k a
- Data.List.Class: execute :: (List l) => l a -> ItemM l ()
- Data.List.Class: filter :: (MonadPlus m) => (a -> Bool) -> m a -> m a
- Data.List.Class: foldlL :: (List l) => (a -> b -> a) -> a -> l b -> ItemM l a
- Data.List.Class: foldrL :: (List l) => (a -> ItemM l b -> ItemM l b) -> ItemM l b -> l a -> ItemM l b
- Data.List.Class: fromList :: (MonadPlus m) => [a] -> m a
- Data.List.Class: fromListT :: (List l) => ListT (ItemM l) a -> l a
- Data.List.Class: genericTake :: (Integral i, List l) => i -> l a -> l a
- Data.List.Class: instance (Monad m) => List (ListT m)
- Data.List.Class: instance List []
- Data.List.Class: joinL :: (List l) => ItemM l (l b) -> l b
- Data.List.Class: joinM :: (List l) => l (ItemM l a) -> l a
- Data.List.Class: lastL :: (List l) => l a -> ItemM l a
- Data.List.Class: lengthL :: (Integral i, List l) => l a -> ItemM l i
- Data.List.Class: liftListMonad :: (MonadTrans t, Monad (t (ItemM l)), List l) => l a -> ListT (t (ItemM l)) a
- Data.List.Class: repeat :: (MonadPlus m) => a -> m a
- Data.List.Class: scanl :: (List l) => (a -> b -> a) -> a -> l b -> l a
- Data.List.Class: takeWhile :: (List l) => (a -> Bool) -> l a -> l a
- Data.List.Class: toList :: (List l) => l a -> ItemM l [a]
- Data.List.Class: toListT :: (List l) => l a -> ListT (ItemM l) 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) => l (l a) -> l (l a)
- Data.List.Class: zip :: (List l) => l a -> l b -> l (a, b)
- Data.List.Class: zipWith :: (List l) => (a -> b -> c) -> l a -> l b -> l c
- Data.List.Tree: bestFirstSearchOn :: (Ord b, Tree t) => (a -> b) -> t a -> ItemM t a
- Data.List.Tree: bestFirstSearchSortedChildrenOn :: (Ord b, Tree t) => (a -> b) -> t a -> ItemM t a
- Data.List.Tree: bfs :: (Tree t) => t a -> ItemM t a
- Data.List.Tree: bfsLayers :: (Tree t) => t a -> ItemM t (ItemM t a)
- Data.List.Tree: class (List t, List (ItemM t)) => Tree t
- Data.List.Tree: dfs :: (List l, MonadPlus (ItemM l)) => l a -> ItemM l a
- Data.List.Tree: instance (List t, List (ItemM t)) => Tree t
- Data.List.Tree: prune :: (List l, MonadPlus (ItemM l)) => (a -> Bool) -> l a -> l a

Files

generator.cabal view
@@ -1,17 +1,11 @@ Name:                generator-Version:             0.5.1+Version:             0.5.2 Category:            Control-Synopsis:            A list monad transformer and related functions.+Synopsis:            Python-generators notation for creation of monadic lists Description:-    A list monad transformer and a generic List class.-     Consumer and Generator monad transformers to create     and iterate 'ListT's in a manner similar to     Python generators.--    A Tree module for searching and pruning-    trees expressed as 'List's whose underlying monad-    is also a List. License:             BSD3 License-file:        LICENSE Author:              Yair Chuchem@@ -24,11 +18,9 @@ Library   hs-Source-Dirs:      src   Extensions:-  Build-Depends:       base >= 3 && < 5, mtl, MaybeT-  Exposed-modules:     Control.Monad.ListT,-                       Control.Monad.DList,+  Build-Depends:       base >= 3 && < 5, mtl, MaybeT, List+  Exposed-modules:     Control.Monad.DList,                        Control.Monad.Consumer,-                       Control.Monad.Generator,-                       Data.List.Class,-                       Data.List.Tree+                       Control.Monad.Generator   Ghc-Options:         -O2 -Wall+
− src/Control/Monad/ListT.hs
@@ -1,112 +0,0 @@-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances #-}---- Module is called ListT because List is taken by mtl---- | A list monad transformer / a monadic list.------ Monadic list example:---   A program which reads numbers from the user and accumulates them.------ > import Control.Monad.ListT (ListT)--- > import Data.List.Class (execute, joinM, repeat, scanl, takeWhile)--- > import Prelude hiding (repeat, scanl, takeWhile)--- >--- > main =--- >   execute . joinM . fmap print .--- >   scanl (+) 0 .--- >   fmap (fst . head) .--- >   takeWhile (not . null) .--- >   fmap reads .--- >   joinM $ (repeat getLine :: ListT IO (IO String))--module Control.Monad.ListT (-  ListItem(..), ListT(..), foldrListT-) where--import Control.Applicative (Applicative(..))-import Control.Monad (MonadPlus(..), ap, liftM)--- import Control.Monad.Cont.Class (MonadCont(..))-import Control.Monad.Error.Class (MonadError(..))-import Control.Monad.Reader.Class (MonadReader(..))-import Control.Monad.State.Class (MonadState(..))-import Control.Monad.Trans (MonadTrans(..), MonadIO(..))-import Data.Monoid (Monoid(..))--data ListItem l a =-  Nil |-  Cons { headL :: a, tailL :: l a }--data ListT m a = ListT { runListT :: m (ListItem (ListT m) a) }---- | foldr for ListT-foldrListT :: Monad m => (a -> m b -> m b) -> m b -> ListT m a -> m b-foldrListT consFunc nilFunc list = do-  item <- runListT list-  case item of-    Nil -> nilFunc-    Cons x xs -> consFunc x $ foldrListT consFunc nilFunc xs---- for mappend, fmap, bind-foldrListT' :: Monad m =>-  (a -> ListT m b -> ListT m b) -> ListT m b -> ListT m a -> ListT m b-foldrListT' consFunc nilFunc =-  ListT . foldrListT step (runListT nilFunc)-  where-    step x = runListT . consFunc x . ListT---- like generic cons except using that one--- would cause an infinite loop-cons :: Monad m => a -> ListT m a -> ListT m a-cons x = ListT . return . Cons x--instance Monad m => Monoid (ListT m a) where-  mempty = ListT $ return Nil-  mappend = flip (foldrListT' cons)--instance Monad m => Functor (ListT m) where-  fmap func = foldrListT' (cons . func) mempty--instance Monad m => Monad (ListT m) where-  return = ListT . return . (`Cons` mempty)-  a >>= b = foldrListT' mappend mempty $ fmap b a--instance Monad m => Applicative (ListT m) where-  pure = return-  (<*>) = ap--instance Monad m => MonadPlus (ListT m) where-  mzero = mempty-  mplus = mappend--instance MonadTrans ListT where-  lift = ListT . liftM (`Cons` mempty)---- YUCK:--- I can't believe I'm doing this,--- for compatability with mtl's ListT.--- I hate the O(N^2) code length auto-lifts. DRY!!--instance MonadIO m => MonadIO (ListT m) where-  liftIO = lift . liftIO--{---- TODO: understand and verify this instance :)-instance MonadCont m => MonadCont (ListT m) where-  callCC f =-    ListT $ callCC thing-    where-      thing c = runListT . f $ ListT . c . (`Cons` mempty)--}--instance MonadError e m => MonadError e (ListT m) where-  throwError = lift . throwError-  catchError m = ListT . catchError (runListT m) . (runListT .)--instance MonadReader s m => MonadReader s (ListT m) where-  ask = lift ask-  local f = ListT . local f . runListT--instance MonadState s m => MonadState s (ListT m) where-  get = lift get-  put = lift . put-
− src/Data/List/Class.hs
@@ -1,239 +0,0 @@-{-# LANGUAGE FlexibleContexts, RankNTypes, TypeFamilies #-}---- | The 'List' class and actions for lists--module Data.List.Class (-  -- | The List typeclass-  List (..),-  -- | List operations for MonadPlus-  cons, fromList, filter, repeat,-  -- | Standard list operations-  takeWhile, genericTake, scanl,-  transpose, zip, zipWith,-  -- | Non standard List operations-  foldlL, toList, execute, joinM, lengthL, lastL,-  -- | Convert between List types-  convList, transformListMonad, liftListMonad-  ) where--import Control.Monad (MonadPlus(..), ap, join, liftM)-import Control.Monad.Identity (Identity(..))-import Control.Monad.ListT (ListT(..), ListItem(..), foldrListT)-import Control.Monad.Trans (MonadTrans(..))-import Data.Function (fix)-import Prelude hiding (-  filter, repeat, scanl, takeWhile, zip, zipWith)---- | A class for list types.--- Every list has an underlying monad.-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 :: ItemM l (l b) -> l b-  -- | foldr for 'List's.-  -- the result and 'right side' values are monadic actions.-  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 (ItemM l) a-  toListT = convList-  -- | Convert from a 'ListT'.-  ---  -- Can be done with a foldrL but included in type-class for efficiency.-  fromListT :: ListT (ItemM l) a -> l a-  fromListT = convList--instance List [] where-  type ItemM [] = Identity-  joinL = runIdentity-  foldrL = foldr-  toListT = fromList--instance Monad m => List (ListT m) where-  type ItemM (ListT m) = m-  joinL = ListT . (>>= runListT)-  foldrL = foldrListT-  toListT = id-  fromListT = id---- | Prepend an item to a 'MonadPlus'-cons :: MonadPlus m => a -> m a -> m a-cons = mplus . return---- | Convert a list to a 'MonadPlus'------ > > fromList [] :: Maybe Int--- > Nothing--- > > fromList [5] :: Maybe Int--- > Just 5-fromList :: MonadPlus m => [a] -> m a-fromList = foldr (mplus . return) mzero---- | Convert between lists with the same underlying monad-convList :: (ItemM l ~ ItemM k, List l, List k) => l a -> k a-convList =-  joinL . foldrL step (return mzero)-  where-    step x = return . cons x . joinL---- | filter for any MonadPlus------ > > filter (> 5) (Just 3)--- > Nothing-filter :: MonadPlus m => (a -> Bool) -> m a -> m a-filter cond =-  (>>= f)-  where-    f x-      | cond x = return x-      | otherwise = mzero---- for foldlL and scanl-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-    astep x rest = return $ (`t` rest) . (`step` x)-    t cur = joinVals cur . (`ap` return cur)---- | An action to do foldl for 'List's-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 => (a -> b -> a) -> a -> l b -> l a-scanl =-  foldlL' consJoin $ const mzero-  where-    consJoin cur = cons cur . joinL--genericTake :: (Integral i, List l) => i -> l a -> l a-genericTake count-  | count <= 0 = const mzero-  | otherwise = foldlL' joinStep (const mzero) next Nothing-  where-    next Nothing x = Just (count, x)-    next (Just (i, _)) y = Just (i - 1, y)-    joinStep Nothing = joinL-    joinStep (Just (1, x)) = const $ return x-    joinStep (Just (_, x)) = cons x . joinL---- | Execute the monadic actions in a 'List'-execute :: List l => l a -> ItemM l ()-execute = foldlL const ()---- | 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--takeWhile :: List l => (a -> Bool) -> l a -> l a-takeWhile cond =-  joinL . foldrL step (return mzero)-  where-    step x-      | cond x = return . cons x . joinL-      | otherwise = const $ return mzero---- | An action to transform a 'List' to a list------ > > runIdentity $ toList "hello!"--- > "hello!"-toList :: List l => l a -> ItemM l [a]-toList =-  foldrL step $ return []-  where-    step = liftM . (:)---- | Consume a list (execute its actions) and return its length------ > > runIdentity $ lengthL [1,2,3]--- > 3-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------ > > import Data.List.Tree (bfs)--- > > bfs (transformListMonad (\(Identity x) -> [x, x]) "hey" :: ListT [] Char)--- > "hheeeeyyyyyyyy"-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-    t = joinL . trans-    step x = return . cons x . t---- | Lift the underlying monad of a list and transform it to a ListT.------ Doing plain 'transformListMonad lift' instead doesn't give the compiler--- the same knowledge about the types.-liftListMonad ::-  (MonadTrans t, Monad (t (ItemM l)), List l) =>-  l a -> ListT (t (ItemM l)) a-liftListMonad = transformListMonad lift--zip :: List l => l a -> l b -> l (a, b)-zip as bs =-  r0 (toListT as) (toListT bs)-  where-    r0 xx yy =-      joinL $ do-        xi <- runListT xx-        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-        Nil -> mzero-        Cons y ys ->-          cons (x, y) $ r0 xs ys---- zipWith based on zip and not vice versa,--- because the other way around hlint compains "use zip".-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 => l a -> ItemM l a-lastL = foldlL (const id) undefined--repeat :: MonadPlus m => a -> m a-repeat = fix . cons--transpose :: List l => l (l a) -> l (l a)-transpose matrix =-  joinL $ toList matrix >>= r . map toListT-  where-    r xs = do-      items <- mapM runListT xs-      return $ case filter isCons items of-        [] -> mzero-        citems ->-          cons (fromList (map headL citems)) .-          joinL . r $ map tailL citems-    isCons Nil = False-    isCons _ = True-
− src/Data/List/Tree.hs
@@ -1,184 +0,0 @@-{-# LANGUAGE FlexibleContexts, FlexibleInstances, ScopedTypeVariables, UndecidableInstances #-}---- | Functions for iterating trees.--- A 'List' whose underlying monad is also a 'List' is a tree.------ It's nodes are accessible, in contrast to the list monad,--- which can also be seen as a tree, except only its leafs--- are accessible and only in "dfs order".------ > import Control.Monad.Generator--- > import Data.List.Class (genericTake, takeWhile, toList, lastL)--- >--- > bits = t ""--- > t prev =--- >   generate $ do--- >     yield prev--- >     x <- lift "01"--- >     yields $ t (prev ++ [x])--- >--- > > take 3 (bfsLayers bits)--- > [[""],["0","1"],["00","01","10","11"]]--- >--- > > take 10 (bfs bits)--- > ["","0","1","00","01","10","11","000","001","010"]--- >--- > > dfs (genericTake 4 bits)--- > ["","0","00","000","001","01","010","011","1","10","100","101","11","110","111"]--- >--- > > toList $ genericTake 3 bits--- > [["","0","00"],["","0","01"],["","1","10"],["","1","11"]]------ Examples of pruning with 'prune' and 'takeWhile':------ > > dfs . takeWhile (not . isSuffixOf "11") $ genericTake 4 bits--- > ["","0","00","000","001","01","010","1","10","100","101"]--- >--- > > lastL . takeWhile (not . isSuffixOf "11") $ genericTake 4 bits--- > ["000","001","010","01","100","101","1"]--- >--- > > lastL . prune (not . isSuffixOf "11") $ genericTake 4 bits--- > ["000","001","010","100","101"]----module Data.List.Tree (-  Tree, dfs, bfs, bfsLayers, bestFirstSearchOn,-  prune, bestFirstSearchSortedChildrenOn-  ) where--import Control.Monad (MonadPlus(..), guard, join, liftM)-import Control.Monad.ListT (ListT(..), ListItem(..))-import Data.List.Class (-  List(..), cons, foldlL, joinM,-  transformListMonad, transpose)---- | A 'type-class synonym' for Trees.-class (List t, List (ItemM t)) => Tree t-instance (List t, List (ItemM t)) => Tree t--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, MonadPlus (ItemM l)) => l a -> ItemM l a-dfs = search join--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 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 t => t a -> ItemM t a-bfs = join . bfsLayers--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-        yi <- runListT yy-        return $ case (xi, yi) of-          (Cons x xs, Cons y ys)-            | f y > f x -> cons x . merge2 xs $ cons y ys-            | otherwise -> cons y $ merge2 (cons x xs) ys-          (x, y) -> mplus (t x) (t y)-    t Nil = mzero-    t (Cons x xs) = cons x xs---- | Best First Search given a scoring function.-bestFirstSearchOn ::-  (Ord b, Tree t) => (a -> b) -> t a -> ItemM t a-bestFirstSearchOn func =-  fromListT . search (mergeOn func) . toListTree--mergeOnSortedHeads ::-  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-    case item of-      Nil -> return mzero-      Cons xx yys -> do-        xi <- runListT xx-        return $ case xi of-          Nil -> mergeOnSortedHeads f yys-          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-        case xi of-          Nil -> return yyy-          Cons x xs -> bury' x xs yyy-    bury' x xs yyy = do-      yyi <- runListT yyy-      case yyi of-        Nil -> return . return $ cons x xs-        Cons yy yys -> do-          yi <- runListT yy-          case yi of-            Nil -> bury' x xs yys-            Cons y ys-              | f x <= f y -> return . cons (cons x xs) $ cons (cons y ys) yys-              | otherwise -> return . cons (cons y ys) =<< bury' x xs yys---- | 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 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, MonadPlus (ItemM l)) => (a -> Bool) -> l a -> l a-prune cond =-  joinM . liftM r-  where-    r x = do-      guard $ cond x-      return x-