簡體   English   中英

如何在haskell的函數參數中傳遞列表?

[英]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)

我有兩個問題

  1. 如何調用過濾器? 我所知道的是,您通過了p ,這是一個列表

  2. 老實說,我一般不知道什么是多態類型,而且我無法弄清楚過濾器函數的多態類型。

我不了解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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM