2017-11-18 70 views
3

我所談論的一個例子是takeWhileHaskell中的「隱形」函數參數如何工作?

takeWhile :: (a -> Bool) -> [a] -> [a] 

用法示例

takeWhile (< 3) [1,2,3,4,1,2,3,4] == [1,2] 

從我可以告訴(< 3)成爲(a < 3)其中a是要檢查在列表中的當前項目。

這是如何在Haskell做,我會怎麼能夠移動其中a去,所以我可以做類似

takeWhile ((length a) < 4) ["aaa", "aaaaa"] 
+3

如果你正在尋找谷歌果汁:這種語法,你省略了符號中綴運算符的一個操作數,稱爲_section_。 '(<3)'表示'(\ x - > x <3)'和'(「abc」++)'表示'(\ x - >「abc」++ x)'。 –

回答

9

(< 3)被稱爲「部分」,僅適用於中綴操作符。這是編寫縮寫函數的語法糖。 (< 3)相當於\x -> x < 3(3 <)相當於\x -> 3 < x

因此,(< 3)是返回Bool的一個參數的函數。這正是takeWhile的期望。

隨着length,你必須寫在全面的功能:

takeWhile (\x -> length x < 4) ["aaa", "aaaaa"] 

或定義自己的功能,您可以咖喱:

shorterThan n x = length x < n 

takeWhile (shorterThan 4) ["aaa", "aaaaa"] 

如果你喜歡冒險,你可以寫

takeWhile ((< 4) . length) ["aaa", "aaaaa"] 

或者可能是以更可讀的方式

(??) = flip (.) 

takeWhile (length ?? (< 4)) ["aaa", "aaaaa"] 
+0

Haskell已經訓練了我很多東西來閱讀從右到左的函數組成,因此'''版本對我來說可讀性較差。 – 4castle

+0

@ 4castle這是一個作文,但不要這樣讀。考慮到 ??作爲變量的佔位符。 「東西的長度小於四」。 –

3

有無處可去,你要記住,在Haskell每個功能currified,所以,想在(+)功能,可以做下,想在第一類型:

(+) :: Num a => a -> a -> a 

現在我可以做我的自定義Plusone精選,plusTwo等,如此之快得益於curryfication,因爲

(+) :: Num a => a -> a -> a 

有 「隱paranthesis」,真的是這樣的:

(+) :: Num a => a -> (a -> a) 

意思給我一個號碼給你一個功能回來,所以:

plusOne :: Num a => a -> a 
plusOne = (+1) 

plusTwo :: Num a => a -> a 
plusTwo = (+2) 

你能看到什麼?你給予它只是兩個參數中的一個變換的(+)在一個新的功能,也會有相同的<>功能,您可以創建功能greaterThanTen是這樣的:在你的takeWhile (< 3)例如

greaterThanTen :: (Num a, Ord a) => a -> a 
greaterThanTen = (>10) 

所以你(< 3)是功能「小於3」,如果你「讀」所有的功能將是「拿n而小於3」

你可以在控制檯通過詢問類型:t命令

:t (< 3) 
(< 3) :: (Num a, Ord a) => a -> Bool 
+2

但請注意'(> 10)4'與'(>)10 4'完全不同。雖然currying/partial應用程序可以讓我們修正第一個參數,但section的語法允許使用'(10 <)和'(10 <)' - 這不僅僅是在工作中起作用,它還接受編譯器的特殊解析和處理。 – chi

+0

@chi非常感謝你,像你這樣的專家,我每天都會學到新東西:),就像......昨天!如果我的記憶沒有失敗,非常感謝評論和時間 –

3

takeWhile的第一個參數是謂詞;這是您的一元函數(< 3),當參數具有數值語義並且小於3時,這是正確的。這個選項適用於每個列表成員,當謂詞首次不成立時,這個選項組成一個新列表並終止。已通過的元素組成結果列表。

你的例子幾乎是正確的,你只能將它轉換成謂詞形式,即創建一個一元函數,當參數(字符串)的長度小於4時,這是真實的。這可以通過例如

(\a -> (length a) < 4) 

然後

takeWhile (\a -> (length a) < 4) ["aaa", "aaaaa"] 

應該做你的期望。

相關問題