2014-11-20 31 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] 

底線我猜是,在第一個例子,你要改變的其他方式的類型比第二個。列表列表變成只是一個列表的地步發生了變化,您添加數字的方式也會發生變化。