map_reduce :: ( Ord ki, Ord ko ) => ( (ki, vi) -> [(ko,vm)] ) -- ^ distribute -> ( ko -> [vm] -> Maybe vo ) -- ^ collect -> Map ki vi -- ^ eingabe -> Map ko vo -- ^ ausgabe map_reduce distribute collect input = M.map ( \ ( Just x ) -> x ) $ M.filter isJust $ M.mapWithKey collect $ M.fromListWith (++) $ map ( \ (ko,vm) -> (ko,[vm]) ) $ concat $ map distribute $ M.toList $ input