2012-09-27 52 views

回答

18

斷裂問題稍微開明分解成概念上的步驟:

  • 你想做些什麼,以列表的每一個元素,這是由map函數提供的一般操作。使用它,你可以忽略這個列表,並且只考慮你需要用一個元素做什麼。

  • 你想把兩個數字相乘。在函數的任何一次使用中,這些數字中的一個將是常量,所以我們可以給它一個名稱作爲函數的參數:mult x = ...。現在我們可以把x作爲一個常數,只考慮另一個數字。

  • 另一個數字不是常量,所以你需要一個函數,而不僅僅是一個簡單的表達式。 Haskell提供「運營商部分」來完成這項工作,如(*)這樣的中綴運營商,所以使用x我們得到了(x *)

  • 備份出來的最後幾步,你現在給x的名稱,並創建一個函數,你傳遞給map

mult x = map (x *) 

...和你實際上是在這一點上完成的,如果你想成爲的話。但是,初學者可能會更清楚地列出一個明確的論點:

mult x ys = map (x *) ys 

雖然這兩種形式都做同樣的事情。

9

我最初有點不屑一顧golfy風格回答了這個,所以讓我們再試一次。我的目的是雙重的:贖回自己寫的不知天高地厚的睡眠剝奪回答一個新人,:-),並嘗試在該點自由風格提示:

mult_l = map . (*) 

是什麼代碼呢?

這是有幫助的流水線方式纔想起來:

  • 該代碼需要(*)飼料它map

  • (*)是什麼類型的?那麼,這是Num a => a -> a -> a。這意味着它確實什麼?輸入一個數字(稱爲x),並給你另一個函數,這個函數會 - 如果給出另一個數字(稱之爲y) - 計算x「times」y。 (我把「時代」括號因爲Num是一個類型類...)

  • 現在你要組成(*)mapmap做什麼?那麼,讓我們看看它的類型:(a -> b) -> [a] -> [b]。所以現在,map將函數作爲參數並將該函數應用於列表的每個成員。

現在想想作文是如何工作的:(f . g) x = f (g x)

如果給一個說法,說2:

mult_l 2 

真的

(map . (*)) 2 

這是真的剛:現在

map (* 2) 

map有兩個參數,它需要一個功能(它說「你想要我什麼要做什麼?「),它需要一個列表(它說」你想讓我做什麼?「)。 map然後獲取該列表中的每個項目,並將該函數應用於元素。

這意味着,如果你把一樣的東西:

map (* 2) [1,2,3] 

然後映射將採取列表,並期待在第一個元素,然後乘以2,再看第二個元素,等...

所以類型的map . (*)Num a => a -> [a] -> [a],因爲它發生在一些x,然後到map喂高階函數\x -> (* x)

現在你面臨的挑戰問題(因爲你是哈斯克爾的新手),如何編寫map?我會給你一個提示:

  • 如果你想在空列表上映射一個函數,那麼你返回空列表。
  • 如果您想將功能映射到列表頭部以及其尾部,請先將頭部應用到頭部,然後對列表的其餘部分執行相同的操作。

在此之外,您將獲得map的遞歸定義以及相關的歸納原理。

你可能會困惑的另一件事是:爲什麼我必須寫map . (*)而不僅僅是map (*)。如果你仔細想想這一段時間,你可能會變得像到point free style

+2

確實,這些職業高爾夫球手會寫'地圖。(*)'並完成它。要達到這一點需要一些複雜性,所以感謝C.A.McCann記錄大部分旅程。 – pigworker

+2

解釋高爾夫FTW! – pigworker

6

由於沒有人談論列表解析,所以只是告訴另一種方式。

mult x ys = [i*x | i <- ys] 
+0

純粹是爲了我的興趣,爲什麼downvote ..?我同意它不以同樣的方式解釋事情,並且可能不適合初學者,但@Satvik並沒有聲稱它是,這是一個很好的選擇 –

+0

@KristopherMicinski我更喜歡map自己的列表解析。我只是建議還有其他的方式來做這件事,你可以選擇任何你喜歡的東西。 – Satvik

+0

我的理解是,我的問題依然存在,雖然對我來說也不是「規範」的方式,但我認爲這不是一種倒退,它不是一種固有的壞方法,而且證明另一個目的是有啓發性的。 –

相關問題