2016-01-20 106 views
0

我通過一些在LYAH的例子讀,我碰到這個代碼片段來到之間使用:差異在預定義的類型類和基本類型

replicate' :: (Num i, Ord i) => i -> a -> [a] 
replicate' n x 
    | n <= 0 = [] 
    | otherwise = x:replicate' (n-1) x 

這是網絡版,但我也有一個這本書的副本,它有這個代替:

replicate' :: Int -> a -> [a] 
replicate' n x 
    | n <= 0 = [] 
    | otherwise = x:replicate' (n-1) x 

我已經試過這兩個出來,他們都工作,但我的問題是:

這些是實現不同的,當笑我使用類型類而不是常規類型嗎?

+5

'(Num,Ord)'太弱,無法確保理智的行爲。它應該可能要求'Integral'。 – dfeuer

+0

@dfeuer:詳細說明一下,如果你使用複雜數字的集合,你需要一個實例Ord a = Ord(Complex a)'(可以說這是'Set'中的一個設計缺陷)並且那麼問題「複製(0:+ 1)foo」是什麼意思?「擡起頭來。法律concat。複製一個。複製b ===複製(a * b)'將會被打破,我想! – yatima2975

+1

@ yatima2975,另一個值得關注的問題是「Num Double」和「Ord Double」的存在。我認爲還可以設想一種類型,表達與非標準分析(無限小)相關的想法,即使完全理智也可能對「複製」不利。 – dfeuer

回答

2

第二個版本僅適用於Int作爲第一個參數。第一個版本更加通用,可用於NumOrd類型類型中的任何類型。類型類定義了用於數字類型的基本操作。在這種情況下,replicate'需要能夠從參數n中減去1。 Ord定義比較操作。這是因爲你使用<=。請注意,Int在這兩個類型類中,因此它支持兩個必需的操作。通過使用更通用的類型簽名來聲明該函數,replicate'可以與支持所需操作的任何其他類型一起使用。

+0

正確答案。但值得添加的是:GHC *可能*爲更窄類型聲明的版本生成更好的代碼 - 在某些情況下*。 (不要硬編碼任何函數來使用沒有基準的'Int'!) –