有什么样的约束'约束'在哈斯克尔意味着

时间:2016-12-13 12:26:52

标签: haskell

我对Haskell很新鲜,我试图通过编写一些代码来理解语言。我只熟悉关于ghci的非常简单的指令:head,tail,sum,(*)等 - 非常简单。

我想要做的功能是为任意数量维度的向量求解毕达哥拉斯定理。这看起来像这样:平方根(a ^ 2 + b ^ 2 + c ^ 2 ......)

我在ghci中可以做几行,我试图做一个函数如下:

sq x = x*x

b = map sq [1,2,3]

a = sum b

x = sqrt b

当我这样做时,我尝试包含许多种类的签名, 目前我的功能如下:

mod :: [Num a] => a
mod x = sqrt a
    where a = sum [b]
            where [b] = map sq [x]

当我尝试运行它时,我不明白这个问题:

Expected a constraint, but ‘[Num a]’ has kind ‘*’
    • In the type signature:
        Main.mod :: [Num a] => a

2 个答案:

答案 0 :(得分:12)

需要调整的一些事项:

0)mod不是函数的好名称,因为它是标准库中模数函数的名称。我会改为称呼norm

1)您打算写的类型签名是:

norm :: Num a => [a] -> a

[a]是包含a类型元素的列表类型。 Num a之前的=>不是{+ 1>}类型,而是约束,它指定a必须是数字类型(或者更准确地说,它必须是Num类的实例。 [Num a] =>导致您看到的错误,因为给定方括号,类型检查器将其视为尝试使用列表类型而不是约束。

Num a问题外,您已从签名中遗漏了结果类型。更正的签名反映出您的函数采用数字列表并返回一个数字。

2)Num a约束对于您要执行的操作来说太弱了。要使用sqrt,您需要的不仅仅是数字类型,而是一个Floating的实例(参见左下角对此答案的评论):

GHCi> :t sqrt
sqrt :: Floating a => a -> a

因此,您的签名应为

norm :: Floating a => [a] -> a

3)[x]是一个包含单个元素x的列表。如果您的参数已经是一个列表,正如类型签名所示,则无需将其括在方括号中。然后,您的功能变为:

norm :: Floating a => [a] -> a
norm x = sqrt a
    where a = sum b
            where b = map sq x

或者,更整洁,没有第二个where - 阻止:

norm :: Floating a => [a] -> a
norm x = sqrt (sum b)
    where b = map sq x

答案 1 :(得分:7)

如您所知,可以按类型对值进行分类。 "foo"类型为[Char]Just 'c'类型为Maybe Char,等等。

同样,类型可以按种类进行分类。您可以为其提供值的所有具体类型都有*种。您可以使用GHCi中的:k命令来查看:

> :k Int
Int :: *
> :k Maybe Int
Maybe Int :: *

类型构造函数也有种类。它们本质上是类型值函数,因此它们的类型与常规函数类似。

> :t id
id :: a -> a
> :k Maybe
Maybe :: * -> *

但是Num a是什么?它不是一种类型,因此没有类型*。它不是类型构造函数,因此它没有箭头类型。它是新的东西,所以创造了一种新的形式来描述它。

> :k Num Int
Num Int :: Constraint

并且Num本身是Constraint值函数:它取值*并生成Constraint

> :k Num
Num :: * -> Constraint

具有种类Constraint的东西用于指定特定类型必须是其实例的类型类。它是类型签名中=>之前可能出现的值。它也是instance“函数”的“论据”:

instance Num Int where
  ...