我是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语言类似,其中约束,抽象或具体,在声明中混合在一起)
答案 0 :(得分:4)
Integral
不是类型:它是类型类。它描述了对类型的约束。
所以,签名:
someFunction :: (Integral a) => a -> Bool -> a
表示“只要a
是Integral
的实例,此函数就可以使用。
(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}}是没有类型参数的类型。)