import qualified Data.Map as M
map_reduce :: ( Ord ki, Ord ko )
=> ( (ki, vi) -> [(ko,vm)] ) -- ^ distribute
-> ( ko -> [vm] -> vo ) -- ^ collect
-> M.Map ki vi -- ^ eingabe
-> M.Map ko vo -- ^ ausgabe
map_reduce distribute collect input
= M.mapWithKey collect
$ M.fromListWith (++)
$ map ( \ (ko,vm) -> (ko,[vm]) )
$ concat $ map distribute
$ M.toList $ input