我有以下功能:
which (x:xs) = worker x xs
worker x [] = x
worker x (y:ys)
| x > y = worker y ys
| otherwise = worker x ys
我想知道如何定义上述函数which
和worker
的类型签名?
例如,以下哪种方式最适合作为工作人员的类型签名?
worker :: Num a => a -> [a] -> a
,
或
worker :: Ord a => a -> [a] -> a
?
我真的很困惑,不知道我应该选择哪三个。我很感激你的想法。感谢。
答案 0 :(得分:6)
如果定义没有显式类型签名的函数,Haskell将推断出最常见的类型。如果您不确定,这是了解如何阅读您的定义的最简单方法;然后,您可以将其复制到源代码中。一个常见的错误是错误地键入一个函数,然后在其他地方出现令人困惑的类型错误。
无论如何,您可以通过在ghci中输入Num
或阅读文档来获取:i Num
课程的信息。 Num
课程为您提供+
,*
,-
,negate
,abs
,signum
,fromInteger
,以及Eq
和Show
的所有功能。请注意,<
和>
不存在!要求Num
的值并尝试比较它们实际上会产生类型错误 - 不是每种数字都可以比较。
所以它应该是Ord a => ...
,因为Num a => ...
如果你尝试了它会产生类型错误。
答案 1 :(得分:3)
如果您考虑一下您的功能,您会发现which xs
会返回xs
中的最小值。什么可以有最低价值?一个Ord
可用的东西列表!
答案 2 :(得分:2)
询问ghci,看看它的内容。我只是将您的代码复制粘贴到文件中并将其加载到ghci中。然后我用:t
这是一个特殊的ghci命令来确定某事物的类型。
ghci> :t which
which :: (Ord t) => [t] -> t
ghci> :t worker
worker :: (Ord a) => a -> [a] -> a
Haskell的类型推断在大多数情况下非常聪明;学会信任它。其他答案足以涵盖在这种情况下应该使用Ord
的原因;我只是想确保ghci被明确地提到作为确定某事物类型的技术。
答案 3 :(得分:0)
修改:评论后改变了我的回答。
这取决于您想要比较的内容。如果您希望能够比较Double
,Float
,Int
,Integer
和Char
,请使用Ord
。如果您只想比较Int
,请使用Int
。
如果您有另外这样的问题,只需查看类型类的实例,以告知您希望在函数中使用哪些类型。
答案 4 :(得分:0)
我总是使用Ord类型约束。它是最通用的,因此可以更频繁地重复使用。
使用Num over Ord没有任何优势。
Int可能有一个小优势,因为它不是多态的,也不需要字典查找。如果我需要性能,我会使用Ord并使用specialize pragma。