[英]How do you pass list in a function parameter in haskell?
我知道這個問題以前已經被問過很多次了,我已經仔細閱讀了,但並不能幫助我回答這類問題。 我是Haskell的新手,
假設我們有以下內容:
filter p [] = []
filter p (h:l) = if (p h) then (h:(filter p l)) else (filter p l)
如何調用過濾器? 我所知道的是,您通過了p
,這是一個列表
老實說,我一般不知道什么是多態類型,而且我無法弄清楚過濾器函數的多態類型。
我不了解if語句中函數過濾器的作用。
如果您能在這兩個問題上協助我,我將不勝感激。
有很多資源可以解釋多態性,但是我不理解它們。
p
不是列表。 p
是謂詞的縮寫,通常是指帶值並返回Bool
的函數的術語。 列表是filter
的第二個參數。
您如何稱呼過濾器? 您需要閱讀許多haskell書籍之一。 馬上。 一些例子:
filter (> 5) [1, 6, 2, 8, 9, 3] -- [6, 8, 9]
filter (== 'z') "bazzz" -- "zzz" (String === [Char])
這里(> 5) :: Int -> Bool
和(== 'z') :: Char -> Bool
是謂詞。
多態非常松散地表示不同類型的形式相同:
filter :: (a -> Bool) -> [a] -> [a]
filter
必須適用於任何類型a
。 因此,特定的a
對實現者是未知的,並且該函數無法假定有關a
任何信息。 a
是通過在調用位置的函數的用戶選擇。
順便說一句。 弄清楚允許執行以下功能是一個有趣的小練習:
:: a -> a
(提示:它只能做一件事,名字就給它了,所以我省略了)
你也能想到的filter
作為函數族所實施完全相同,只是在不同的a
。 其中一些可能是:
:: (Int -> Bool) -> [Int] -> [Int]
:: (Char -> Bool) -> [Char] -> [Char]
:: (Foo -> Bool) -> [Foo] -> [Foo]
在學習新概念時,SO並不是一個很好的起點。 你真的應該抓一本好書。
在深入了解實現之前,我們應該確定filter
的類型。 實際上,您通常應該設計函數的類型簽名,而無需編寫任何實際代碼……但是損壞已經在這里完成了。 (謹此陳辭,您現在可以實際詢問GHCi 您的實現的類型是什么……但是同樣,這是倒退的,所以我不會深入研究它。)
那么,您希望filter
完成什么工作? 確實應該列出一個清單。 您想根據每個元素可能具有的某些屬性來提取該列表中的某些元素。 但是filter
不應該有任何難以理解的假設,即要使用什么條件,即應該是任何元素類型的列表的類型 。 在Haskell中,我們將其寫為[a]
(實際上是∀ a . [a]
簡寫,請讀成“對於您可能考慮的所有元素類型-例如A
–這是[A]
類型的列表”)。
然后,應通過一個額外的參數確定實際標准是什么: 過濾謂詞 。 例如,您可能要從整數列表中過濾所有小於5
數字–您可以使用謂詞(<5) :: Int -> Bool
。 通常,對於您的[a]
列表,您需要使用a- a -> Bool
類型a -> Bool
謂詞。 最終結果將具有與您傳入時相同的列表元素,因此filter
將具有簽名
filter :: [a] -> (a -> Bool) -> [a]
...除約定外,我們將謂詞放在首位,即
filter :: (a -> Bool) -> [a] -> [a]
讓我們檢查一下這是有道理的...例如,我們想要
> filter ((<5) :: Int -> Bool) ([4,9,3] :: [Int])
在這種情況下a ~ Int
filter :: (Int -> Bool) -> [Int] -> [Int]
...是的,這很有意義。
現在,您實際上開始擔心實現了。 有兩種通用方法:
解構列表。 基本上,列表只能有兩種顯示方式:它可以包含某些內容,也可以為空。 空很容易,因為在這種情況下,您只能返回一個空列表,而不能返回其他任何內容。 你甚至不能使用謂詞,因為沒有你可以用它檢查元素,因此僅僅通過匹配丟棄_
:
filter _ [] = []
(或者,您也可以將謂詞匹配為p
,但是人們會懷疑:發生了什么 鼠標 p
?)
如果列表不為空,則可以從其中直接彈出一個元素:
filter p (h:l) = …
在這里, h
是頭元素, l
是列表的其余部分。 太好了,我們現在有了一個類型a
的元素,讓我們看看謂詞告訴我們的內容!
filter p (h:l) = if ph then … else …
因此,如果謂詞得到滿足,我們希望在最終結果中再次看到h
,不是嗎? 實際上,最終結果應以h
開頭
filter p (h:l) = if ph then h : … else …
最終結果的其余部分應與輸入列表的其余部分有關。 我們可以照原樣傳遞then h : l else …
,但這意味着我們只能控制head元素的條件。 不,我們仍然必須過濾列表的其余部分:
filter p (h:l) = if ph then h : filter pl else …
實際上,即使謂詞沒有滿足h
,我們也想這樣做,除非我們不添加它:
filter p (h:l) = if ph then h : filter pl else filter pl
然后你去了:
filter _ [] = []
filter p (h:l) = if p h then h : filter p l else filter p l
if
看起來有些笨拙,則首選語法實際上是警衛 (它們執行相同的操作)
filter _ [] = []
filter p (h:l)
| p h = h : filter p l
| otherwise = filter p l
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.