确定函数的类型

时间:2014-06-22 16:57:20

标签: haskell functional-programming

我试图找出Haskell确定函数类型的方式。我写了一个示例代码:

compareAndIncrease a b = 
    if a > b then a+1:b:[]
    else a:b:[]

构建基于a>的列表。 b比较。然后我用:t命令检查了它的类型:

compareAndIncrease :: (Ord a, Num a) => a -> a -> [a]

好的,所以我需要一个类型类Ord用于比较,Num用于数值计算(比如a + 1)。然后我拿参数a和b并获得一个回复列表(a-> a-> [a])。一切似乎都很好。但后来我找到了一个复制数字的函数:

replicate' a b
| a ==0 = []
| a>0 = b:replicate(a-1) b

请注意,普通,库复制函数在内部使用,而不是复制'一个。它应该类似于compareAndIncrease,因为它使用比较,数值运算并返回一个列表,所以我认为它会像这样工作:

replicate' :: (Ord a, Num a) => a -> a -> [a]

然而,当我使用:t查看时,我得到了这个结果:

replicate' :: Int -> t -> [t]

我继续摆弄这个功能并将其名称改为repval,现在它是:

有人可以向我解释发生了什么吗?

2 个答案:

答案 0 :(得分:4)

GHCi是一个很好用的工具:

*Main> :type replicate
replicate :: Int -> a -> [a]

您可以根据复制定义replicate'(为了清楚起见,我重命名您的变量):

replicate' n e
  | -- blah blah blah
  | n > 0 = e : replicate (n - 1) e  

由于您致电replicate (n - 1),因此类型检查器会推断n - 1必须具有Int类型,从中可以推断出n必须具有Int类型,从中可以推断出replicate'的类型为Int -> a -> [a]

如果您以递归方式编写了replicate',请使用replicate'而不是replicate,那么您将获得

*Main> :type replicate'
replicate' :: (Ord a, Num a) => a -> a1 -> [a1]

修改

正如Ganesh Sittampalam指出的那样,最好将类型约束为Integral,因为复制一小部分次数并不合理。

答案 1 :(得分:4)

您的推理中的关键缺陷是replicate实际上只需要Int来获取复制计数,而不是更通用的数字类型。

如果您改为使用genericReplicate,那么您的论证将大致有效。

genericReplicate :: Integral i => i -> a -> [a]

但请注意,约束为Integral而不是Num,因为Num涵盖任何类型的数字,包括实数,而只重复整数次才有意义。