使用 Data.Map.map 对值求和

using Data.Map.map to sum values

我想用 Data.Map.map 函数对 Doubles 求和。

所以我想要这样的功能:

sumTheDoubles :: Mapping.Map Char [(Char, Double)] -> Mapping.Map Char [(Char, Double)]

我想用 Data.Map.map 函数对所有双打求和:

让我们说

sumTheDoubles (fromList [('i', [('a', 1.0), ('n', 2.0)])])

应该做: 1.0 + 2.0 -->

(fromList [('i', [('a', 3.0), ('n', 3.0)])])

但我的主要问题是,我不太了解如何使用 Data.Map.map 函数访问双打。

渐渐地,我到了这条线:

sumTheDoubles' f = Mapping.map (\a -> map ((\b -> \(c,d) -> (c,b)) ((sum.map snd) a)) a) f

我是怎么得到这个结果的? 我从最高级别开始。然后我根据需要定义了越来越多的功能。总是我首先确定个别功能的类型。最后,我将函数转换为 lambda 形式(从底部开始)并将它们应用到顶层。

module Main where

import qualified Data.Map as Mapping

sumTheDoubles :: Mapping.Map Char [(Char, Double)] -> Mapping.Map Char [(Char, Double)]
sumTheDoubles a = Mapping.map map2 a

-- combine sum and replace
map2 :: [(Char, Double)] -> [(Char, Double)]
map2 a = map (map3 $ map4 a) a

-- replace snd
map3 :: Double -> (Char, Double) -> (Char, Double)
map3 a (b,c) = (b,a)

-- sum Doubles
map4 :: [(Char, Double)] -> Double
map4 a = (sum.map snd) a

main = putStrLn $ show $ sumTheDoubles $ Mapping.fromList [('i', [('a', 1.0), ('n', 2.0)])]

输出:

fromList [('i',[('a',3.0),('n',3.0)])]

构造一个Map Char [(Char, Double)]似乎意义不大:列表中所有二元组的第二项将相同。构造一个 Map Char Double 更有意义,因此我们对值列表的二元组的第二项求和。

我们可以构建这样的地图:

sumTheDoubles :: Mapping.Map Char [(Char, Double)] -> Mapping.Map Char Double
sumTheDoubles = <strong>fmap</strong> (<strong>sum</strong> . map snd)

我们在这里使用 fmap :: Functor f => (a -> b) -> f a -> f b 将函数应用于 Map 中的所有值,并且对于这些值中的每一个,我们首先构建原始列表的第二项列表,并且然后使用 sum 将这些加在一起。

如果你真的想使用元素列表,你可以使用:

sumTheDoubles :: Mapping.Map Char [(Char, Double)] -> Mapping.Map Char Double
sumTheDoubles = fmap (<strong>\xs -> map (</strong>sum (map snd xs) <strong><$) xs</strong>)