如果我执行以下操作
functionS (x,y) = y
:t functionS
functionS :: (a, b) -> b
现在具有此功能:
functionC x y = if (x > y) then True else False
:t function
我希望得到:
functionC :: (Ord a, Ord b) => a -> b -> Bool
但是我得到了
functionC :: Ord a => a -> a -> Bool
GHCI似乎可以接受之前的2个结果,但是为什么给我第二个结果呢?为什么未定义类型变量a和b?
答案 0 :(得分:3)
我认为您可能会误读类型签名。毫无疑问,您用来指导思想的示例令人困惑。特别是在您的元组示例中
functionS :: (a,b) -> b
functionS (x,y) = y
符号(_,_)
表示两种不同的含义。在第一行中,(a,b)
指的是 type ,其对的类型为第一个元素的类型为a
,第二个元素的类型为b
。在第二行中,(x,y)
指的是特定的一对,其中x
的类型为a
,而y
的类型为b
。尽管此“双关语”提供了有用的助记符,但在您初次使用它时可能会造成混淆。我希望对的类型是常规类型的构造函数:
functionS :: Pair a b -> b
functionS (x,y) = y
因此,继续您的问题。在签名中,您会得到
functionC :: Ord a => a -> a -> Bool
a
是类型。 Ord a
说类型a
的元素相对于彼此是可排序的。该函数接受两个 same 类型的参数。可排序的某些类型是Integer
(按数字),String
(按字典顺序),以及其他一些。这意味着您可以知道两个Integer
中哪个较小,或者两个String
中哪个较小。但是,我们不一定知道如何判断Integer
是否比String
小(这很好!您见过哪种shenanigans了吗? javascript必须支持无类型的相等性吗?Haskell根本不需要解决这个问题!)。这就是这个签名的意思-只有一个单一的可排序类型a
,并且该函数接受了同一类型的两个元素。
您可能仍然想知道为什么functionS
的签名具有两个不同的类型变量。这是因为没有约束将它们限制为相同,例如必须将它们彼此相对排序。 functionS
在一对组成部分都为整数的对上同样有效,就像一个是整数而另一个是字符串一样。没关系Haskell总是选择最有效的最普通类型。因此,如果不强迫它们相同,则它们将不同。
有更多的技术方法可以解释所有这些,但是我觉得应该有一个直观的解释。希望对您有所帮助!