diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+1.4.7
+
+* Add `foldByKey{,Hash}Map` functions
+
 1.4.6
 
 * Add `nest`/`predropWhile`/`drop`/`dropM`
diff --git a/foldl.cabal b/foldl.cabal
--- a/foldl.cabal
+++ b/foldl.cabal
@@ -1,6 +1,6 @@
 Name: foldl
-Version: 1.4.6
-Cabal-Version: >=1.8.0.2
+Version: 1.4.7
+Cabal-Version: >=1.10
 Build-Type: Simple
 License: BSD3
 License-File: LICENSE
@@ -49,6 +49,7 @@
         Control.Foldl.Optics
         Control.Foldl.Internal
     GHC-Options: -O2 -Wall
+    Default-Language: Haskell2010
 
 Benchmark benchmarks
     Type: exitcode-stdio-1.0
@@ -59,6 +60,7 @@
         criterion,
         foldl
     GHC-Options: -O2 -Wall -rtsopts -rtsopts -with-rtsopts=-T
+    Default-Language: Haskell2010
 
 Test-Suite doctest
     Type: exitcode-stdio-1.0
@@ -68,3 +70,4 @@
         base,
         doctest >= 0.16
     GHC-Options: -threaded
+    Default-Language: Haskell2010
diff --git a/src/Control/Foldl.hs b/src/Control/Foldl.hs
--- a/src/Control/Foldl.hs
+++ b/src/Control/Foldl.hs
@@ -39,6 +39,7 @@
 {-# LANGUAGE ExistentialQuantification #-}
 {-# LANGUAGE FlexibleContexts          #-}
 {-# LANGUAGE RankNTypes                #-}
+{-# LANGUAGE ScopedTypeVariables       #-}
 {-# LANGUAGE Trustworthy               #-}
 
 module Control.Foldl (
@@ -99,7 +100,9 @@
     , set
     , hashSet
     , map
+    , foldByKeyMap
     , hashMap
+    , foldByKeyHashMap
     , vector
     , vectorM
 
@@ -151,6 +154,7 @@
 import Data.Foldable (Foldable)
 import Data.Functor.Identity (Identity, runIdentity)
 import Data.Functor.Contravariant (Contravariant(..))
+import Data.HashMap.Strict (HashMap)
 import Data.Map.Strict (Map, alter)
 import Data.Maybe (fromMaybe)
 import Data.Monoid hiding ((<>))
@@ -940,6 +944,28 @@
     done = id
 {-# INLINABLE map #-}
 
+
+{- | Given a 'Fold', produces a 'Map' which applies that fold to each @a@ separated by key @k@.
+
+>>> fold (foldByKeyMap Control.Foldl.sum) [("a",1), ("b",2), ("b",20), ("a",10)]
+fromList [("a",11),("b",22)]
+-}
+foldByKeyMap :: forall k a b. Ord k => Fold a b -> Fold (k, a) (Map k b)
+foldByKeyMap f = case f of
+  Fold (step0 :: x -> a -> x) (ini0 :: x) (end0 :: x -> b) ->
+    let
+      step :: Map k x -> (k,a) -> Map k x
+      step mp (k,a) = Map.alter addToMap k mp where
+        addToMap Nothing         = Just $ step0 ini0 a
+        addToMap (Just existing) = Just $ step0 existing a
+
+      ini :: Map k x
+      ini = Map.empty
+
+      end :: Map k x -> Map k b
+      end = fmap end0
+    in Fold step ini end where
+
 {-|
 Fold pairs into a hash-map.
 -}
@@ -950,6 +976,27 @@
     step m (k, v) = HashMap.insert k v m
     done = id
 {-# INLINABLE hashMap #-}
+
+{- | Given a 'Fold', produces a 'HashMap' which applies that fold to each @a@ separated by key @k@.
+
+>>> fold (foldByKeyHashMap Control.Foldl.sum) [("a",1), ("b",2), ("b",20), ("a",10)]
+fromList [("a",11),("b",22)]
+-}
+foldByKeyHashMap :: forall k a b. (Hashable k, Eq k) => Fold a b -> Fold (k, a) (HashMap k b)
+foldByKeyHashMap f = case f of
+  Fold (step0 :: x -> a -> x) (ini0 :: x) (end0 :: x -> b) ->
+    let
+      step :: HashMap k x -> (k,a) -> HashMap k x
+      step mp (k,a) = HashMap.alter addToHashMap k mp where
+        addToHashMap Nothing         = Just $ step0 ini0 a
+        addToHashMap (Just existing) = Just $ step0 existing a
+
+      ini :: HashMap k x
+      ini = HashMap.empty
+
+      end :: HashMap k x -> HashMap k b
+      end = fmap end0
+    in Fold step ini end where
 
 -- | Fold all values into a vector
 vector :: Vector v a => Fold a (v a)
