2016-01-20 66 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'!) –