假设我正在编写一个函数,它接受一个整数列表并只返回列表中小于 5.2 的那些整数。我可能会做这样的事情:
belowThreshold = filter (< 5.2)
够简单了吧?但现在我想将此函数限制为仅使用 [Int] 类型的输入列表,这是出于我自己的设计原因。这似乎是一个合理的要求。唉,没有。限制类型的声明如下:
belowThreshold :: [Integer] -> [Integer]
belowThreshold = filter (< 5.2)
导致类型错误。那么这里有什么故事呢?为什么执行过滤器(< 5.2)似乎将我的输入列表转换为 double ?如何制作仅接受整数列表且仅返回整数列表的此函数的版本?为什么类型系统讨厌我?
最佳答案
在添加注释之前检查 ghci 中的 underThreshold 的推断类型:
> :t belowThreshold
belowThreshold :: [Double] -> [Double]
当您说“约束此功能”时,听起来您期望的是
Num a => [a] -> [a]
。当您添加 [Integer] -> [Integer]
注释时,您实际上是在更改函数的类型。要完成这项工作,请使用显式转换:
belowThreshold = filter ((< 5.2) . fromIntegral)
现在
belowThreshold :: [Integer] -> [Integer]
就像你想要的那样。但是在与 5.2 比较之前,整数被转换为 double 数。那么为什么需要转换呢?类型错误可能误导了您:与 5.2 相比,整数列表没有转换为 double 数,真正的问题是只有 double 数可以与 double 数进行比较,因此您必须将 double 数列表传递给
belowThreshold
。 Haskell 没有隐式转换,甚至数字之间也没有。如果您想要转换,则必须自己编写。I want to constrain this function to only work with input lists of type [Int] for design reasons of my own. This seems like a reasonable request.
好吧,从类型系统的角度来看,没有。这是合理的代码吗?
'c' < "foo"
那这个呢?
12 < "bar"
所有这些值都是
Ord
的实例,但您不能将它们与 (<)
一起使用。 Haskell 没有隐式转换。因此,即使两个值都是 Num
和 Ord
的实例,如果它们的类型不同,您也无法将它们与 (<)
进行比较。
关于Haskell:将 Double 类型的函数限制为仅适用于整数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2442840/