2014-11-20 27 views
6

阅读“用Haskell功能思考”我遇到了一个程序计算的一部分,要求重写map sum (map (x:) xss)作为map (x+) (map sum xss)Haskell - 如何转换地图总和(地图(x :) xss)到地图(x +)(地图总和xss)

凭直觉我知道,这是有道理的......

如果你有一些名单,你会总结,但总结之前,那些相同的列表中,您也将添加一个元素的“x ',那么就像获得一个列表的和列表的数量并将x的值添加到它们中的每一个一样。

但我想知道如何使用等式推理将其转换为另一个。我觉得我错过了能帮助我理解的法律或规则。

回答

12

用法律

map f (map g list) === map (f . g) list 

我们可以推断

map sum (map (x:) xss) = 
map (sum . (x:)) xss = 

ETA-扩大给一个说法与

map (\xs -> sum . (x:) $ xs) xss = 

替换为(f . g) x === f (g x)

工作10

sum (x:xs) = x + sum xs 
sum [] = 0 

所以

map (\xs -> sum (x:xs)) xss = 
map (\xs -> x + sum xs) xss = 

f (g x) === (f . g) x

map (\xs -> (x +) . sum $ xs) xss = 

ETA-降低拉姆达

map ((x +) . sum) xss = 

使用上面的第一个法则的反面

map (x+) (map sum xss) 
+0

我不同意列表的理解,但它肯定是一个品味的问题。为什么不使用'(。)'的​​定义并说'map(sum。(x :))xss = map(\ xs - > sum(x:xs))xss = map(\ xs - > x + sum xs)= ...'? – kosmikus 2014-11-20 20:07:03

+0

@kosmikus呃,个人品味。在这种情况下,它是非常不重要的,但我可以看到在整个时间内保持“地图”的论点。 – bheklilr 2014-11-20 20:08:00

+0

@kosmikus好看吗? – bheklilr 2014-11-20 20:10:18

0

我建议你看看类型,让他们指导你完成转换。

> let xss = [[1], [2], [3]] 
> :t xss 
xss :: Num t => [[t]] 
> map sum xss  -- basically compacting the lists 
[1,2,3] 
> :t map sum xss -- into just a list of numbers 
map sum xss :: Num b => [b] 

接下来我们需要做加法

> :t (+5) 
(+5) :: Num a => a -> a 
> :t map (+5)  -- no magic in this 
map (+5) :: Num b => [b] -> [b] 
> map (+5) (map sum xss) 
[6,7,8] 

底线我猜是,在第一个例子,你要改变的其他方式的类型比第二个。列表列表变成只是一个列表的地步发生了变化,您添加数字的方式也会发生变化。