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

时间:2017-12-17 10:26:41

标签: haskell

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

someFunction :: (Integral a) => a -> Bool -> a 

这将编译。

someFunction :: (Integral a, Bool b) => a -> b -> a 

但鉴于此,编译器会抱怨:

• 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

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

谢谢!

感谢快速回答的人。他们引导我进入下一个问题:在宣言中不同地方存在争论约束背后的想法是什么? (与C语言类似,其中约束,抽象或具体,在声明中混合在一起)

2 个答案:

答案 0 :(得分:4)

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

所以,签名:

someFunction :: (Integral a) => a -> Bool -> a 

表示“只要aIntegral的实例,此函数就可以使用

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

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

instance Integral Int where
    -- (declarations here)

以下是您自己的类型类的示例:Sizeable

class Sizeable s where
    size :: s -> Int

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

instance Sizeable [a] where
    size = length

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

instance Sizeable (a,b,c) where
    size _ = 3

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

sizePlusOne s = (size s) + 1

这将是类型:

sizePlusOne :: (Sizeable s) => s -> Int

答案 1 :(得分:2)

=>左侧的项目是类型约束。 Haskell使用类型类。在Java等编程语言中,类型类最好被视为接口

例如在Haskell中有一个类Eq

class Eq a where
  (==) :: a -> a -> Bool
  (/=) :: a -> a -> Bool

现在,我们可以通过将Int Num声明为instance来为Num类型类型class创建一个“{em>成员”,和**实现属于Eq的函数。比方说我们想让(正) Peano数成为data Peano = Zero | Succ Peano 的一个实例,然后我们首先将Peano数字定义为:

Eq

现在我们可以将其设为instance Eq Peano where Zero == Zero = True s(x) == s(y) = x == y _ == _ = False Zero /= Zero = False s(x) /= s(y) = x /= y _ /= _ = True

的实例
Peano

现在我们可以将两个==个实例与Peano进行比较,并将Eq注册为someFunction :: Eq a => a -> a -> a -> Bool someFunction x y z = x == y && y == z 的实例。所以这意味着如果我们写下这样的东西:

a

然后Peano可以是Eq Peano,因为我们要求==(在左侧)成立。

因此,类型类用于允许您使用抽象函数(例如/=Bool),而不知道如何为具体类型定义这些函数。

另一方面,

Bool b 不是类型类,它是具体类型。所以你不能写Eq Peano。它在语法上也没有意义,因为类型类需要参数(即Bool),而{{1}}是没有类型参数的类型。)

相关问题