Haskell 函数参数类型声明的区别

Che*_*zen 5 haskell

我是 Haskell 的新手。我只是对这里的参数类型声明之间的差异感到困惑:

someFunction :: (Integral a) => a -> Bool -> a 
Run Code Online (Sandbox Code Playgroud)

这将编译。

someFunction :: (Integral a, Bool b) => a -> b -> a 
Run Code Online (Sandbox Code Playgroud)

然而考虑到这一点,编译器会抱怨:

• Expecting one fewer arguments to ‘Bool’
  Expected kind ‘* -> Constraint’, but ‘Bool’ has kind ‘*’
• In the type signature:
    someFunction :: (Integral a, Bool b) => a -> b -> a
Run Code Online (Sandbox Code Playgroud)

这两个声明有什么区别?我试图用谷歌搜索,但似乎没有直接的答案。

谢谢!


感谢您的快速回答。他们将我引向下一个问题:在声明中的不同位置设置参数约束背后的想法是什么?(与 C 类语言相比,在声明中将抽象或具体的约束混合在一起)

AJF*_*mar 5

Integral不是类型:它是一个类型类。它描述了对类型的约束。

所以,签名:

someFunction :: (Integral a) => a -> Bool -> a 
Run Code Online (Sandbox Code Playgroud)

意思是“只要a是 的一个实例Integral,这个函数就可以对它起作用”。

你的第二个例子 (Integral a, Bool b) => a -> b -> a没有意义,因为它Bool是一个类型,而不是一个类型类。

成为 的一个实例是Integral什么意思?嗯,这意味着在某个地方,有人为某种类型写过,例如Int:

instance Integral Int where
    -- (declarations here)
Run Code Online (Sandbox Code Playgroud)

这是您自己的类型类的示例Sizeable:

class Sizeable s where
    size :: s -> Int
Run Code Online (Sandbox Code Playgroud)

我们可以将其视为具有相关大小的类型,该大小由size函数定义。所以,我们可以添加一些实例:

instance Sizeable [a] where
    size = length

instance Sizeable (a,b) where
    size _ = 2

instance Sizeable (a,b,c) where
    size _ = 3
Run Code Online (Sandbox Code Playgroud)

所以,我们可以编写函数:

sizePlusOne s = (size s) + 1
Run Code Online (Sandbox Code Playgroud)

这将具有以下类型:

sizePlusOne :: (Sizeable s) => s -> Int
Run Code Online (Sandbox Code Playgroud)

  • 说`someFunction :: (Integral a, Bool b)`没有真正的用例就像说巧克力米长​​的梯子没有真正的用例一样。这是域中的不匹配,没有意义。问题在于,`(Integral a, Bool b)` 看起来像是类 C 语言中的函数签名,但实际上与此关系不大。 (7认同)