diff --git a/Control/GroupWith.hs b/Control/GroupWith.hs
--- a/Control/GroupWith.hs
+++ b/Control/GroupWith.hs
@@ -1,4 +1,4 @@
-
+{-# LANGUAGE Safe, ScopedTypeVariables #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Control.GroupWiths
@@ -7,29 +7,42 @@
 -- Maintainer  :  ukoehler@techoverflow.net
 -- Stability   :  provisional
 -- Portability :  portable
---
+-- 
 -- A collection of grouping utility functions.
 -- For a given function that assigns a key to objects,
 -- provides functions that group said objects into a multimap
 -- by said key.
---
+-- 
 -- This can be used similarly to the SQL GROUP BY statement.
---
+-- 
 -- Provides a more flexible approach to GHC.Exts.groupWith
---
+-- 
 -- > groupWith (take 1) ["a","ab","bc"] == Map.fromList [("a",["a","ab"]), ("b",["bc"])]
+--
+-- In order to use monadic / applicative functions as key generators,
+-- use the A- or M-postfixed variants like 'groupWithA' or 'groupWithMultipleM'
+--
+-- 
 --  
 -----------------------------------------------------------------------------
 module Control.GroupWith(
         MultiMap,
         groupWith,
         groupWithMultiple,
-        groupWithUsing
+        groupWithUsing,
+        groupWithA,
+        groupWithM,
+        groupWithMultipleM,
+        groupWithUsingM
     ) where
 
-import Data.Map (Map)
-import qualified Data.Map as Map
+import Data.Map.Strict (Map)
+import qualified Data.Map.Strict as Map
 
+import Control.Arrow (first, second)
+import Control.Applicative (Applicative, (<$>), liftA2, pure)
+import Data.Traversable (sequenceA)
+
 type MultiMap a b = Map a [b]
 
 -- | Group values in a list by a key, generated
@@ -42,7 +55,7 @@
           -> MultiMap b a -- ^ The resulting key --> value multimap
 groupWith f xs = Map.fromListWith (++) [(f x, [x]) | x <- xs]
 
--- | Like groupWith, but the identifier-generating function
+-- | Like 'groupWith', but the identifier-generating function
 --   may generate multiple keys for each value (or none at all).
 --   The corresponding value from the original list will be placed
 --   in the identifier-corresponding map entry for each generated
@@ -53,7 +66,7 @@
                   -> [a] -- ^ The list to be grouped
                   -> MultiMap b a -- ^ The resulting map
 groupWithMultiple f xs = 
-  let identifiers x = [(val, [x]) | val <- f x]
+  let identifiers x = [(val, [x]) | val <- vals] where vals = f x
   in Map.fromListWith (++) $ concat [identifiers x | x <- xs]
 
 -- | Like groupWith, but uses a custom combinator function
@@ -65,3 +78,59 @@
           -> [a] -- ^ The list to be grouped
           -> Map b c -- ^ The resulting key --> transformed value map
 groupWithUsing t c f xs = Map.fromListWith c $ map (\v -> (f v, t v)) xs
+
+-- | Fuse the functor from a tuple
+fuseT2 :: Applicative f => (f a, f b) -> f (a,b)
+fuseT2 = uncurry $ liftA2 (,)
+
+-- | Like 'fuseT2', but only requires the first element to be boxed in the functor
+fuseFirst :: Applicative f => (f a, b) -> f (a,b)
+fuseFirst = fuseT2 . second pure
+
+-- | Move the applicative functor to the outmost level by first mapping
+--   fuseT2First and then applying 'Data.Traversable.sequenceA' to move
+--   the functor outside the list
+fuseFirstList :: Applicative f  => [(f a, b)] -> f [(a,b)]
+fuseFirstList = sequenceA . map fuseFirst
+
+-- | Group values in a list by a key, generated by a given applicative function.
+--   Applicative version of 'groupWith'. See 'groupWith' for documentation.
+groupWithA :: (Ord b, Applicative f) =>
+             (a -> f b) -- ^ The function used to map a list value to its key
+          -> [a] -- ^ The list to be grouped
+          -> f (MultiMap b a) -- ^ The resulting key --> value multimap
+groupWithA f xs =
+  Map.fromListWith (++) <$> fuseFirstList [(f x, [x]) | x <- xs]
+
+-- | Alias for 'groupWithA', with additional monad constraint
+groupWithM :: (Ord b, Monad m, Applicative m) =>
+             (a -> m b) -- ^ The function used to map a list value to its key
+          -> [a] -- ^ The list to be grouped
+          -> m (MultiMap b a) -- ^ The resulting key --> value multimap
+groupWithM = groupWithA
+
+-- | Like 'groupWithM', but the identifier-generating function
+--   may generate multiple keys for each value (or none at all).
+--   See 'groupWithMultiple' for further behavioural details.
+--   
+--   Note that it's impossible to define this for applicatives:
+--   See http://stackoverflow.com/a/6032260/2597135
+groupWithMultipleM :: (Ord b, Monad m, Applicative m) =>
+                     (a -> m [b]) -- ^ The function used to map a list value to its keys
+                  -> [a] -- ^ The list to be grouped
+                  -> m (MultiMap b a) -- ^ The resulting map
+groupWithMultipleM f xs = 
+  let identifiers x = (\vals -> [(val, [x]) | val <- vals]) <$> f x
+      idMap = concat <$> (mapM identifiers xs)
+  in Map.fromListWith (++) <$> idMap
+
+-- | Like 'groupWithM', but uses a custom combinator function
+groupWithUsingM :: (Ord b, Monad m, Applicative m) =>
+             (a -> m c) -- ^ Transformer function used to map a value to the resulting type
+          -> (c -> c -> c) -- ^ The combinator used to combine an existing value
+                           --   for a given key with a new value
+          -> (a -> m b) -- ^ The function used to map a list value to its key
+          -> [a] -- ^ The list to be grouped
+          -> m (Map b c) -- ^ The resulting key --> transformed value map
+groupWithUsingM t c f xs =
+  Map.fromListWith c <$> mapM (\v -> fuseT2 (f v, t v)) xs
diff --git a/GroupWithTest.hs b/GroupWithTest.hs
--- a/GroupWithTest.hs
+++ b/GroupWithTest.hs
@@ -4,6 +4,7 @@
 import Control.Monad
 import Control.GroupWith
 import Data.Map (Map)
+import Data.Maybe (fromJust)
 import Data.List (sort)
 import qualified Data.Map as Map
 
@@ -47,7 +48,7 @@
         -- We need to specialize here, because it's ⊥
         let fn = error "This function should never be called" :: Int -> Int
             data_ = [] :: [Int]
-            result = groupWith fn data_
+            result = groupWithUsing id (+) fn data_
         in result `shouldSatisfy` ((==) 0 . Map.size)
     it "should be usable for counting" $
         -- Instead of building up lists, we count the number of elements
@@ -76,3 +77,56 @@
             data_ = [] :: [Int]
             result = groupWithMultiple fn data_
         in result `shouldSatisfy` ((==) 0 . Map.size)
+  {-
+    NOTE: We will use Maybe as monad / applicative functor for this test
+  -}
+  describe "groupWithM" $ do
+    it "should group a simple value correctly" $
+        let data_ = ["a","abc","ab","bc"]
+            fn = Just . take 1
+            ref = Map.fromList [("a",["a","abc","ab"]),("b",["bc"])]
+            result = groupWithM fn data_
+        in (fromJust result, ref) `shouldSatisfy` multimapTupleEq
+    it "should return an empty map when given an empty list" $
+        -- We need to specialize here, because it's ⊥
+        let fn = error "This function should never be called" :: Int -> Maybe Int
+            data_ = [] :: [Int]
+            result = groupWithM fn data_
+        in (fromJust result) `shouldSatisfy` ((==) 0 . Map.size)
+    -- Fuzzing, couldn't get this to compile properly yet
+    -- it "should not crash for any input string list" $
+    --    property $ (\d -> groupWith (take 1) d `seq` True)
+  describe "groupWithMultipleM" $ do
+    it "should group correctly given a simple list" $
+        let data_ = ["a","abc","ab","bc"]
+            fn x = Just [take 1 x, take 2 x]
+            -- Note the multiple "a"s in the first line:
+            -- one from `take 1`, one from `take 2`
+            ref = Map.fromList [("a",["a","a","abc","ab"]),
+                                ("ab",["ab","abc"]),
+                                ("b",["bc"]),
+                                ("bc",["bc"])]
+            result = groupWithMultipleM fn data_
+        in (fromJust result, ref) `shouldSatisfy` multimapTupleEq
+    it "should return an empty map when given an empty list" $
+        -- We need to specialize here, because it's ⊥
+        let fn = error "This function should never be called" :: Int -> Maybe [Int]
+            data_ = [] :: [Int]
+            result = groupWithMultipleM fn data_
+        in (fromJust result) `shouldSatisfy` ((==) 0 . Map.size)
+  describe "groupWithUsingM" $ do
+    it "should return an empty map when given an empty list" $
+        -- We need to specialize here, because it's ⊥
+        let fn = error "This function should never be called" :: Int -> Maybe Int
+            data_ = [] :: [Int]
+            result = groupWithUsingM return (+) fn data_
+        in (fromJust result) `shouldSatisfy` ((==) 0 . Map.size)
+    it "should be usable for counting" $
+        -- Instead of building up lists, we count the number of elements
+        let t n = return 1 -- For each x, count 1
+            c = (+) -- Sum up the counts
+            fn = return . take 1
+            data_ = ["a","abc","ab","bc"]
+            ref = Map.fromList [("a",3),("b",1)] :: Map String Int
+            result = groupWithUsingM t c fn data_
+        in fromJust result `shouldBe` ref
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-group-by
+group-with
 ========
 
 A Haskell library to classify objects by a function value, just like SQL GROUP BY
diff --git a/changelog b/changelog
new file mode 100644
--- /dev/null
+++ b/changelog
@@ -0,0 +1,10 @@
+** 0.2.x
+
+0.1.0.0 --> 0.2.0.0
+===============
+
+* Support monadic and applicative (where possible) grouping
+
+* Add and fix unit tests for monadic and pure grouping
+
+* Use strict map by default to avoid buildup of thunks
diff --git a/group-with.cabal b/group-with.cabal
--- a/group-with.cabal
+++ b/group-with.cabal
@@ -1,5 +1,5 @@
 name:                group-with
-version:             0.1.0.0
+version:             0.2.0.0
 synopsis:            Classify objects by key-generating function, like SQL GROUP BY
 description:         A library to classify objects into multimaps by using a function generating
                      keys for any object in the list.
@@ -15,7 +15,7 @@
 -- copyright:           
 category:            Data
 build-type:          Simple
-extra-source-files:  README.md
+extra-source-files:  README.md changelog
 cabal-version:       >=1.10
 
 source-repository head
