2011-05-03 63 views
2

我一直受列表工作方式的挑戰,並對整個(x:xs)概念感到困惑。我似乎沒有得到我的頭。試圖讓我的頭(x:xs)和列表?

select :: Ord a => a -> [a] -> [a] 
select y [] = [] 
select y (x:xs) 
    | x < y  = x : select y xs 
    | otherwise = select y xs 

P.S.我確切地知道這個功能是幹什麼的,但是任何人都可以解釋這個過程(特別是包含奇怪的Ord a=>標誌)?

任何有效的策略將不勝感激。

在此先感謝。伊恩。

回答

9

好的。我們來看看這裏的不同語法元素。

行1

select :: Ord a => a -> [a] -> [a] 

這是一種類型聲明。它是一個函數的聲明(因爲它有->類型)。

該函數有兩個參數。

  • 第一個是任何類型的單值,由a(小寫字母表示它是多態類型)表示。
  • 第二個參數是與第一個參數相同的任何類型的列表。

返回值是任何類型的列表,與參數類型相同。

Ord a組件是一個typeclass約束,它表示給出的這個函數的任何類型也必須是Ord類的一個實例。這是一類可以比較的類型。

線2

現在我們來看看第2行:

select y [] = [] 

這是select函數本身的一個定義。它非常簡單,包含兩個參數的模式,以及結果的說明。記載:

如果第一參數是任意值(我們將其命名爲y),第二個參數是空的列表(由[]圖案表示),然後select計算結果爲空列表。

線3

3行包含列出了另一種情況:

select y (x:xs) 

再次,這是select函數的定義的一部分,當所述第二參數的情況下是不是一個空的列表。如果它不是一個空列表,那麼它是一個包含頭部的列表,x和尾部xs。 「cons」構造函數(:)包含列表頭部和尾部。這也是我們如何在列表上進行模式匹配,以提取頭部和尾部。

通過圖案上的列表中的頭和尾匹配,與(x:xs),我們綁定一個新的變量,x到列表的開頭的值,並且xs到列表的尾部的值。

管路4和5

最後兩行是附加警衛該測試和分支基於額外的檢查,如果第二個參數是一個非空列表:

| x < y  = x : select y xs 
| otherwise = select y xs 

x小於第一個參數y時,第一個警衛啓動。如果是這樣,我們在頭返回一個新的列表與x,並再次select應用到尾。

如果不是的話,那麼我們放棄x從列表中,並返回時,尾遞歸調用僅會發生什麼。


有關Haskell的工作原理的詳細信息,我建議入門教科書,如:

這將是值得你的時間。

2

我Haskell是有限的,在最好的,但我給什麼答案,我可以的情況下,其他人不...

select :: Ord a => a -> [a] -> [a] 

這是說:

select函數使用任何類型「a」,使得該類型屬於類型「Ord」(Orderable)。它需要一個類型的實例和一個類型列表,並返回一個類型爲 的列表。

如果有幫助,在Java中,這可表示爲(kindof):

<T implements Comparable> List<T> select(T value, List<T> listOfValues); 

實際的函數定義說:

  • 如果一個空的列表中傳遞,返回空列表,否則
  • 如果傳入的列表的第一個元素小於該值,則返回一個列表,該元素包含該元素附加到列表中的函數app騙列表的其餘部分,否則
  • 返回由附加在從評價函數得到的列表元素的列表(即,沒有第一元素)

編輯:可訂購在上述背景下的裝置「你可以將這種類型的值相互比較以確定哪一個是'第一'」。即,<,=和>操作符是爲類型的值定義的。 「Ord」是由(實際上)Haskell標準庫定義的TypeClass(Prelude?我忘記它叫做什麼)

+0

謝謝您的回答@RHSeeger。不太清楚是什麼意思可訂購的編程方面雖然... – maclunian 2011-05-03 20:18:29

+0

@maclunian:「這種類型的可訂購」簡單,你可以比較這類型,例如兩件事情與'<'。 – delnan 2011-05-03 20:19:48

+0

通常,a =>符號表示約束。它的含義是,該類型必須是指定類型類型的一個實例(Ord執行比較,如<, >和<=)。實際上,只要你想使用未知類型的操作,就需要這種依賴關係。 – fuz 2011-05-03 20:21:12

1

(x:xs)用於與cons單元格進行模式匹配。當你說[1,2,3]時,它實際上是1:(2:(3:[]))的語法糖。因此,當select 1 [1,2,3],被調用:

select y []  = ... -- pattern skipped; [1,2,3] does not match [] 
select y (x:xs) = ... -- pattern used, with y = 1, x = 1, and xs = [2,3] 

因此,在(x:xs)x是列表的第一個項目,xs是剩餘項目。只有列表不爲空時,此模式纔會匹配。

至於Ord a =>語法,它的意思是「如果a是類型Ord的實例」。Int將在這裏工作,因爲它爲Ord一個實例,它看起來是這樣的:

instance Ord Int where 
    (<=) = primitiveIntLessThanOrEqual 

如果你離開了Ord a出來,只是說:select :: a -> [a] -> [a],然後x < y是行不通的,因爲它需要在一個類型的參數類Ord

(<) :: (Ord a) => a -> a -> Bool 
+0

然後,它會做與其他人一樣,不是嗎! – maclunian 2011-05-03 20:21:23

+0

@maclunian:我不明白你的評論。 – fuz 2011-05-03 20:23:25

+0

@FUZxxl我想我現在正在拍照! – maclunian 2011-05-03 20:44:41