2016-03-02 80 views
1
divide_list :: Int -> [Int] -> [Int] -> [Int] -> ([Int], [Int]) 

divide_list n [] l r = (l,r) 
divide_list n (h:t) l r = 
    if h <= n 
     then divide_list n t (h:l) r 
     else divide_list n t l (h:r) 

正如你所看到的我的函數需要的列表Int。如何修改此代碼以獲得更一般的類型?我的意思是例如字符串列表等。參數類型的推廣

+2

一個簡單的解決方案是評估中,無類型簽名的功能,讓ghci推斷你的類型。它應該將'Int'推廣到'Ord a => a'。 – zakyggaps

+0

這是什麼意思:「Ord a => a」? – Gilgamesz

+1

它是任何帶'Ord'實例的'a'類型。在你的函數中使用'<='是需要的。 – zakyggaps

回答

3

爲了使函數具有多態性,您需要在函數的簽名中指定類型變量。類型變量必須以小寫字母指定,以便將它們與以大寫形式指定的特定類型區分開來。

divide_list :: a -> [a] -> [a] -> [a] -> ([a], [a]) 

一個溫柔的介紹報價哈斯克爾教程:

哈斯克爾還採用了多態類型---被 以某種方式對所有類型的普遍量化類型。多態類型 表達式實質上描述了類型的族。例如, (全部a)[a]是由以下類型組成的類型:對於每個類型a, a的列表類型。整數列表(例如[1,2,3]), 字符列表(['a','b','c']),甚至整數列表等等,都是 的所有成員家庭。問題後

編輯在評論:

注意,在你的函數定義使用<=。這是Ord typeclass中定義的函數,因此您必須將多態類型約束爲此類型類的實例。

divide_list :: (Ord a) => a -> [a] -> [a] -> [a] -> ([a], [a]) 
+0

好吧,之後我得到了一個編譯錯誤(這很明顯,因爲Haskell不知道它是什麼意思:((<=)en)。但是如何修復它? – Gilgamesz

+1

這種類型簽名太多態了 - 你需要爲'e <= n'位指定一個'Ord a'實例 – Cactus

+0

好的。如何定義我自己的類型並且讓他成爲Ord? – Gilgamesz

1

您使用的Int是唯一的方面是,鑑於hn,你可以計算h <= n。這是廣義的Ord類型類,所以你的函數可以是多態的過度類型的變量a的任何選擇,只要有一個Ord a實例:

divide_list :: (Ord a) => a -> [a] -> [a] -> [a] -> ([a], [a]) 
+0

這是什麼意思'=>'? – Gilgamesz

+0

https://www.haskell.org/tutorial/classes.html – Cactus