Haskell 中的“约束”是什么意思

2023-12-29

我对 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

有几点需要调整:

0) mod对于您的函数来说不是一个好名称,因为它是标准库中的模函数的名称。我会称之为norm反而。

1)您要写的类型签名是:

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

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

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

2) The Num a对于您想要做的事情来说,约束太弱。为了使用sqrt,您不仅需要有一种数字类型,而且需要有一个实例Floating(参见 leftaroundabout 对此答案的评论):

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-block:

norm :: Floating a => [a] -> a
norm x = sqrt (sum b)
    where b = map sq x
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Haskell 中的“约束”是什么意思 的相关文章

随机推荐