diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c)2011, Thomas Eding
+
+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 Thomas Eding 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/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,6 @@
+#!/usr/bin/runhaskell 
+> module Main where
+> import Distribution.Simple
+> main :: IO ()
+> main = defaultMain
+
diff --git a/monadlist.cabal b/monadlist.cabal
new file mode 100644
--- /dev/null
+++ b/monadlist.cabal
@@ -0,0 +1,50 @@
+name: monadlist
+version: 0.0.1
+cabal-version: -any
+build-type: Simple
+license: BSD3
+license-file: LICENSE
+copyright:
+maintainer: thomasedingcode@gmail.com
+build-depends: base >=3 && <5
+stability:
+homepage:
+package-url:
+bug-reports:
+synopsis: Monadic versions of list functions
+description: Monadic versions of list functions seen in Data.List.
+category: Control
+author: Thomas Eding
+tested-with:
+data-files:
+data-dir: ""
+extra-source-files:
+extra-tmp-files:
+exposed-modules: Control.Monad.ListM
+exposed: True
+buildable: True
+build-tools:
+cpp-options:
+cc-options:
+ld-options:
+pkgconfig-depends:
+frameworks:
+c-sources:
+default-language:
+other-languages:
+default-extensions:
+other-extensions:
+extensions:
+extra-libraries:
+extra-lib-dirs:
+includes:
+install-includes:
+include-dirs:
+hs-source-dirs: src
+other-modules:
+ghc-prof-options:
+ghc-shared-options:
+ghc-options:
+hugs-options:
+nhc98-options:
+jhc-options:
diff --git a/src/Control/Monad/ListM.hs b/src/Control/Monad/ListM.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Monad/ListM.hs
@@ -0,0 +1,380 @@
+-----------------------------------------------------------------------------
+--
+-- Module      :  Control.Monad.ListM
+-- Copyright   :
+-- License     :  AllRightsReserved
+--
+-- Maintainer  :
+-- Stability   :
+-- Portability :
+--
+-- |
+--
+-----------------------------------------------------------------------------
+
+module Control.Monad.ListM (
+  mapMP
+, filterMP
+, intersperseM
+, foldM1
+, joinMap
+, joinMapM
+, anyM
+, allM
+, scanM
+, mapAccumM
+, iterateM
+, takeM
+, dropM
+, splitAtM
+, takeWhileM
+, dropWhileM
+, spanM
+, breakM
+, elemM
+, notElemM
+, lookupM
+, findM
+, partitionM
+, elemIndexM
+, elemIndicesM
+, findIndexM
+, findIndicesM
+, zipWithM3
+, zipWithM4
+, zipWithM5
+, zipWithM6
+, nubM
+, nubByM
+, deleteM
+, deleteByM
+, deleteFirstsM
+, deleteFirstsByM
+, unionM
+, unionByM
+, intersectM
+, intersectByM
+, groupM
+, groupByM
+, sortM
+, sortByM
+, insertM
+, insertByM
+, maximumM
+, maximumByM
+, minimumM
+, minimumByM
+) where
+
+import qualified Prelude
+import Prelude hiding (error, mapM, sequence, and, or)
+
+import Control.Monad hiding (mapM, sequence)
+import Data.Foldable (or, and)
+import Data.List (zip4, zip5, zip6)
+import Data.Maybe (isJust)
+import Data.Traversable (Traversable, mapM, sequence)
+
+
+infixr 5 !, !!!
+
+
+error :: String -> String -> a
+error func msg = Prelude.error $ "Control.Monad.ListM." ++ func ++ ": " ++ msg
+
+notM :: (Monad m) => Bool -> m Bool
+notM = return . not
+
+eqM :: (Eq a, Monad m) => a -> a -> m Bool
+eqM x y = return $ x == y
+
+compareM :: (Ord a, Monad m) => a -> a -> m Ordering
+compareM x y = return $ compare x y
+
+(!) :: (MonadPlus p) => a -> p a -> p a
+x ! y = return x `mplus` y
+
+(!!!) :: (MonadPlus p) => [a] -> p a -> p a
+(!!!) = flip $ foldr (!)
+
+uncurry3 :: (a -> b -> c -> d) -> ((a, b, c) -> d)
+uncurry3 f (x, y, z) = f x y z
+
+uncurry4 :: (a -> b -> c -> d -> e) -> ((a, b, c, d) -> e)
+uncurry4 f (x, y, z, w) = f x y z w
+
+uncurry5 :: (a -> b -> c -> d -> e -> f) -> ((a, b, c, d, e) -> f)
+uncurry5 f (x, y, z, w, s) = f x y z w s
+
+uncurry6 :: (a -> b -> c -> d -> e -> f -> g) -> ((a, b, c, d, e, f) -> g)
+uncurry6 f (x, y, z, w, s, t) = f x y z w s t
+
+mapMP :: (Monad m, MonadPlus p) => (a -> m b) -> [a] -> m (p b)
+mapMP _ [] = return mzero
+mapMP f (x:xs) = do
+  y <- f x
+  liftM (y!) $ mapMP f xs
+
+filterMP :: (Monad m, MonadPlus p) => (a -> m Bool) -> [a] -> m (p a)
+filterMP _ [] = return mzero
+filterMP p (x:xs) = do
+  bool <- p x
+  if bool
+    then liftM (x!) $ filterMP p xs
+    else filterMP p xs
+
+intersperseM :: (Monad m, MonadPlus p) => m a -> [a] -> m (p a)
+intersperseM _ [] = return mzero
+intersperseM _ [x] = return $ return x
+intersperseM m (x:ys) = do
+  z <- m
+  liftM ([x, z] !!!) $ intersperseM m ys
+
+intercalateM :: (Monad m, MonadPlus p) => m (p a) -> [p a] -> m (p a)
+intercalateM m = liftM join . intersperseM m
+
+foldM1 :: (Monad m) => (a -> a -> m a) -> [a] -> m a
+foldM1 _ [] = error "foldM1" "empty list"
+foldM1 f (x:xs) = foldM f x xs
+
+joinMap :: (Monad m) => (a -> m b) -> m a -> m b
+joinMap f = join . liftM f
+
+joinMapM :: (Monad m, MonadPlus p) => (a -> m (p b)) -> [a] -> m (p b)
+joinMapM f = liftM join . mapMP f
+
+anyM :: (Monad m, Traversable t) => (a -> m Bool) -> t a -> m Bool
+anyM p = liftM or . mapM p
+
+allM :: (Monad m, Traversable t) => (a -> m Bool) -> t a -> m Bool
+allM p = liftM and . mapM p
+
+scanM :: (Monad m, MonadPlus p) => (a -> b -> m a) -> a -> [b] -> m (p a)
+scanM _ z [] =  return $ return z
+scanM f z (x:xs) = do
+  z' <- f z x
+  liftM (z!) $ scanM f z' xs
+
+mapAccumM :: (Monad m, MonadPlus p) => (acc -> x -> m (acc, y)) -> acc -> [x] -> m (acc, p y)
+mapAccumM _ z [] = return (z, mzero)
+mapAccumM f z (x:xs) = do
+  (z', y) <- f z x
+  (z'', ys) <- mapAccumM f z' xs
+  return (z'', y!ys)
+
+iterateM :: (Monad m, MonadPlus p) => (a -> m a) -> a -> m (p a)
+iterateM f x = do
+  x' <- f x
+  liftM (x!) $ iterateM f x'
+
+takeM :: (Integral i, Monad m, MonadPlus p) => i -> [m a] -> m (p a)
+takeM _ [] = return mzero
+takeM n (m:ms)
+  | n <= 0 = return mzero
+  | otherwise = m >>= \x -> liftM (x!) $ takeM (n-1) ms
+
+dropM :: (Integral i, Monad m) => i -> [m a] -> m [a]
+dropM _ [] = return []
+dropM n (m:ms)
+  | n <= 0 = sequence $ m:ms
+  | otherwise = m >> dropM (n-1) ms
+
+splitAtM :: (Integral i, Monad m, MonadPlus p) => i -> [m a] -> m (p a, [a])
+splitAtM _ [] = return (mzero, [])
+splitAtM n (m:ms)
+  | n <= 0 = do
+      ys <- sequence $ m:ms
+      return (mzero, ys)
+  | otherwise = do
+      x <- m
+      (xs, ys) <- splitAtM (n-1) ms
+      return (x!xs, ys)
+
+takeWhileM :: (Monad m, MonadPlus p) => (a -> m Bool) -> [a] -> m (p a)
+takeWhileM _ [] = return mzero
+takeWhileM p (x:xs) = do
+  bool <- p x
+  if bool
+    then liftM (x!) $ takeWhileM p xs
+    else return mzero
+
+dropWhileM :: (Monad m) => (a -> m Bool) -> [a] -> m [a]
+dropWhileM _ [] = return []
+dropWhileM p (x:xs) = do
+  bool <- p x
+  if bool
+    then dropWhileM p xs
+    else return $ x:xs
+
+spanM :: (Monad m, MonadPlus p) => (a -> m Bool) -> [a] -> m (p a, [a])
+spanM _ [] = return (mzero, [])
+spanM p (x:xs) = do
+  bool <- p x
+  if bool
+    then do
+      (ys, zs) <- spanM p xs
+      return (x!ys, zs)
+    else return (mzero, x:xs)
+
+breakM :: (Monad m, MonadPlus p) => (a -> m Bool) -> [a] -> m (p a, [a])
+breakM p = spanM $ notM <=< p
+
+elemM :: (Eq a, Monad m) => a -> [a] -> m Bool
+elemM x = liftM isJust . elemIndexM x
+
+notElemM :: (Eq a, Monad m) => a -> [a] -> m Bool
+notElemM x = notM <=< elemM x
+
+lookupM :: (Eq a, Monad m, MonadPlus p) => a -> [m (a, b)] -> m (p b)
+lookupM _ [] = return mzero
+lookupM x (m:ms) = do
+  (k, v) <- m
+  if x == k
+    then return $ return v
+    else lookupM x ms
+
+findM :: (Monad m, MonadPlus p) => (a -> m Bool) -> [a] -> m (p a)
+findM _ [] = return mzero
+findM p (x:xs) = do
+  bool <- p x
+  if bool
+    then return $ return x
+    else findM p xs
+
+partitionM :: (Monad m, MonadPlus p) => (a -> m Bool) -> [a] -> m (p a, [a])
+partitionM _ [] = return (mzero, [])
+partitionM p (x:xs) = do
+  bool <- p x
+  if bool
+    then do
+      (ys, zs) <- partitionM p xs
+      return (x!ys, zs)
+    else return (mzero, x:xs)
+
+elemIndexM :: (Eq a, Integral i, Monad m, MonadPlus p) => a -> [a] -> m (p i)
+elemIndexM x = findIndexM $ eqM x
+
+elemIndicesM :: (Eq a, Integral i, Monad m, MonadPlus p) => a -> [a] -> m (p i)
+elemIndicesM x = findIndicesM $ eqM x
+
+findIndexM :: (Integral i, Monad m, MonadPlus p) => (a -> m Bool) -> [a] -> m (p i)
+findIndexM p = liftM (liftM fst) . findM (p . snd) . zip [0..]
+
+findIndicesM :: (Integral i, Monad m, MonadPlus p) => (a -> m Bool) -> [a] -> m (p i)
+findIndicesM p = liftM (liftM fst) . filterMP (p . snd) . zip [0..]
+
+zipWithM3 :: (Monad m, MonadPlus p) => (a -> b -> c -> m d) -> [a] -> [b] -> [c] -> m (p d)
+zipWithM3 f xs ys = mapMP (uncurry3 f) . zip3 xs ys
+
+zipWithM4 :: (Monad m, MonadPlus p) => (a -> b -> c -> d -> m e) -> [a] -> [b] -> [c] -> [d] -> m (p e)
+zipWithM4 f xs ys zs = mapMP (uncurry4 f) . zip4 xs ys zs
+
+zipWithM5 :: (Monad m, MonadPlus p) => (a -> b -> c -> d -> e -> m f) -> [a] -> [b] -> [c] -> [d] -> [e] -> m (p f)
+zipWithM5 f xs ys zs ws = mapMP (uncurry5 f) . zip5 xs ys zs ws
+
+zipWithM6 :: (Monad m, MonadPlus p) => (a -> b -> c -> d -> e -> f -> m g) -> [a] -> [b] -> [c] -> [d] -> [e] -> [f] -> m (p g)
+zipWithM6 f xs ys zs ws ss = mapMP (uncurry6 f) . zip6 xs ys zs ws ss
+
+nubM :: (Eq a, Monad m, MonadPlus p) => [a] -> m (p a)
+nubM = nubByM eqM
+
+nubByM :: (Monad m, MonadPlus p) => (a -> a -> m Bool) -> [a] -> m (p a)
+nubByM _ [] = return mzero
+nubByM eq (x:xs) = liftM (x!) $ filterM (notM <=< eq x) xs >>= nubByM eq
+
+deleteM :: (Eq a, Monad m) => a -> [a] -> m [a]
+deleteM = deleteByM eqM
+
+deleteByM :: (Monad m) => (a -> a -> m Bool) -> a -> [a] -> m [a]
+deleteByM _ _ [] = return []
+deleteByM eq x (y:ys) = do
+  bool <- eq x y
+  if bool
+    then return ys
+    else liftM (y:) $ deleteByM eq x ys
+
+deleteFirstsM :: (Eq a, Monad m) => [a] -> [a] -> m [a]
+deleteFirstsM = deleteFirstsByM eqM
+
+deleteFirstsByM :: (Monad m) => (a -> a -> m Bool) -> [a] -> [a] -> m [a]
+deleteFirstsByM _ xs [] = return xs
+deleteFirstsByM eq xs (y:ys) = do
+  xs' <- deleteByM eq y xs
+  deleteFirstsByM eq xs' ys
+
+unionM :: (Eq a, Monad m) => [a] -> [a] -> m [a]
+unionM = unionByM eqM
+
+unionByM :: (Monad m) => (a -> a -> m Bool) -> [a] -> [a] -> m [a]
+unionByM eq ys xs = do
+  ys' <- nubByM eq ys
+  ys'' <- foldM (flip $ deleteByM eq) ys' xs
+  return $ xs ++ ys''
+
+intersectM :: (Eq a, Monad m, MonadPlus p) => [a] -> [a] -> m (p a)
+intersectM = intersectByM eqM
+
+intersectByM :: (Monad m, MonadPlus p) => (a -> a -> m Bool) -> [a] -> [a] -> m (p a)
+intersectByM _ [] _ = return mzero
+intersectByM _ _ [] = return mzero
+intersectByM eq (x:xs) ys = do
+  bool <- anyM (eq x) ys
+  if bool
+    then liftM (x!) $ intersectByM eq xs ys
+    else intersectByM eq xs ys
+
+groupM :: (Eq a, Monad m, MonadPlus p, MonadPlus q) => [a] -> m (p (q a))
+groupM = groupByM eqM
+
+groupByM :: (Monad m, MonadPlus p, MonadPlus q) => (a -> a -> m Bool) -> [a] -> m (p (q a))
+groupByM _ [] = return mzero
+groupByM eq (x:xs) = do
+  (ys, zs) <- spanM (eq x) xs
+  liftM ((x!ys)!) $ groupByM eq zs
+
+sortM :: (Ord a, Monad m) => [a] -> m [a]
+sortM = sortByM compareM
+
+sortByM :: (Monad m) => (a -> a -> m Ordering) -> [a] -> m [a]
+sortByM _ [] = return []
+sortByM cmp (x:xs) = sortByM cmp xs >>= insertByM cmp x
+
+insertM :: (Ord a, Monad m) => a -> [a] -> m [a]
+insertM = insertByM compareM
+
+insertByM :: (Monad m) => (a -> a -> m Ordering) -> a -> [a] -> m [a]
+insertByM _ x [] = return [x]
+insertByM cmp x (y:ys) = do
+  ordering <- cmp x y
+  case ordering of
+    GT -> liftM (y:) $ insertByM cmp x ys
+    _ -> return $ x:y:ys
+
+maximumM :: (Ord a, Monad m) => [a] -> m a
+maximumM [] = error "maximumM" "empty list"
+maximumM xs = maximumByM compareM xs
+
+maximumByM :: (Monad m) => (a -> a -> m Ordering) -> [a] -> m a
+maximumByM _ [] = error "maximumByM" "empty list"
+maximumByM cmp xs = foldM1 maxByM xs
+  where
+    maxByM x y = do
+      ordering <- cmp x y
+      return $ case ordering of
+        GT -> x
+        _ -> y
+
+minimumM :: (Ord a, Monad m) => [a] -> m a
+minimumM [] = error "minimumM" "empty list"
+minimumM xs = minimumByM compareM xs
+
+minimumByM :: (Monad m) => (a -> a -> m Ordering) -> [a] -> m a
+minimumByM _ [] = error "minimumByM" "empty list"
+minimumByM cmp xs = foldM1 minByM xs
+  where
+    minByM x y = do
+      ordering <- cmp x y
+      return $ case ordering of
+        GT -> y
+        _ -> x
+
