diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,32 @@
+Copyright Yair Chuchem 2009.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Yair Chuchem nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/List.cabal b/List.cabal
new file mode 100644
--- /dev/null
+++ b/List.cabal
@@ -0,0 +1,24 @@
+Name:                List
+Version:             0.1
+Category:            Control
+Synopsis:            List monad transformer and class
+Description:
+    A List monad transformer and a List class.
+    With standard list operations for Lists
+License:             BSD3
+License-file:        LICENSE
+Author:              Yair Chuchem
+Maintainer:          yairchu@gmail.com
+Homepage:            http://github.com/yairchu/generator/tree
+Cabal-Version:       >= 1.2
+Stability:           experiemental
+Build-type:          Simple
+
+Library
+  hs-Source-Dirs:      src
+  Extensions:
+  Build-Depends:       base >= 3 && < 5, mtl
+  Exposed-modules:     Control.Monad.ListT,
+                       Data.List.Class
+  Ghc-Options:         -O2 -Wall
+
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,3 @@
+import Distribution.Simple
+main = defaultMain
+
diff --git a/src/Control/Monad/ListT.hs b/src/Control/Monad/ListT.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Monad/ListT.hs
@@ -0,0 +1,112 @@
+{-# 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 }
+
+newtype 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
+
diff --git a/src/Data/List/Class.hs b/src/Data/List/Class.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/List/Class.hs
@@ -0,0 +1,266 @@
+{-# 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, lengthL, lastL,
+  merge2On, mergeOn,
+  -- | Operations useful for monadic lists
+  execute, joinM,
+  -- | 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
+
+-- | Merge many lists sorted by a criteria given the criteria
+--
+-- > > mergeOn length [["hi", "hey", "hello"], ["cat", "falcon"], ["banana", "cucumber"]]
+-- > ["hi","cat","hey","hello","banana","falcon","cucumber"]
+mergeOn :: (Ord b, List l) => (a -> b) -> l (l a) -> l a
+mergeOn f = joinL . foldlL (merge2On f) mzero
+
+-- | Merge two lists sorted by a criteria given the criteria
+--
+-- > > merge2On id "01568" "239"
+-- > "01235689"
+merge2On :: (Ord b, List l) => (a -> b) -> l a -> l a -> l a
+merge2On f xx yy =
+  fromListT . joinL $ do
+    xi <- runListT (toListT xx)
+    yi <- runListT (toListT yy)
+    return $ case (xi, yi) of
+      (Cons x xs, Cons y ys)
+        | f y > f x -> cons x . merge2On f xs $ cons y ys
+        | otherwise -> cons y $ merge2On f (cons x xs) ys
+      (Cons x xs, Nil) -> cons x xs
+      (Nil, Cons y ys) -> cons y ys
+      (Nil, Nil) -> mzero
+
