gpt4 book ai didi

haskell - 为什么 3 和 x(被分配为 3)在 Haskell 中具有不同的推断类型?

转载 作者:行者123 更新时间:2023-12-02 15:02:13 25 4
gpt4 key购买 nike

Haskell 中的类型推断有一点学习曲线(至少可以这么说!)。开始学习它的一个好方法是通过简单的例子。因此,以下是类型推断的“hello world”。

考虑以下示例:

Prelude> :t 3
3 :: (Num t) => t
Prelude> let x = 3
Prelude> :t x
x :: Integer

问题是:为什么 3 和 x 有不同的类型?

链接摘要:

阅读下面的答案以获取完整的故事;这只是一个链接摘要:

  1. GHC 类型默认:Haskell Report section4.3.4
  2. GHCi 的扩展类型默认:Using GHCi section2.4.5
  3. 单态限制:Haskellwiki

最佳答案

这里还有另一个因素,在 acfoltzer 包含的一些链接中提到过,但可能值得在这里明确说明。您遇到了 monomorphism restriction 的效果。当你说

let x = 5

您对变量进行了顶级定义。 MR 坚持认为,当这些定义没有类型签名时,应该通过为未解析的类型变量选择(希望)合适的默认实例来专门化为单态值。相比之下,当您使用 :t 请求推断类型时,不会施加此类限制或默认值。所以

> :t 3
3 :: (Num t) => t

因为 3 确实是重载的:任何数字类型都承认它。默认规则选择Integer作为默认数字类型,因此

> let x = 3
> :t x
x :: Integer

但是现在让我们关闭 MR。

> :set -XNoMonomorphismRestriction
> let y = 3
> :t y
y :: (Num t) => t

如果没有 MR,定义就尽可能多态,就像 3 一样重载。只是检查...

> :t y * (2.5 :: Float)
y * (2.5 :: Float) :: Float
> :t y * (3 :: Int)
y * (3 :: Int) :: Int

请注意,根据相关 Num 实例提供的 fromInteger 方法,多态 y = 3 在这些用途中的专门化有所不同。也就是说,y 并不与 3 的特定表示相关联,而是与用于构造 3 的表示的方案相关联。天真的编译,这是缓慢的秘诀,一些人将其视为 MR 的动机。

对于单态限制是大恶还是小恶的争论,我(局部假装)保持中立。我总是为顶级定义编写类型签名,因此我想要实现的目标没有任何歧义,并且 MR 不是重点。

当尝试了解类型系统如何工作时,将类型推断的各个方面分开非常有用

  1. “遵循计划”,将多态定义专门针对特定用例:一个相当稳健的约束解决问题,需要通过回链进行基本统一和实例解析;和

  2. “猜测计划”,泛化类型以将多态类型方案分配给没有类型签名的定义:这非常脆弱,并且您越多地越过基本的 Hindley-Milner 规则,包括类型类、更高阶的多态性,有了 GADT,事情就会变得更奇怪。

了解第一个方法是如何工作的,并理解为什么第二个方法很困难是很好的。类型推断中的许多奇怪之处都与第二个相关,并且与诸如单态限制之类的启发式方法相关,这些启发式方法试图在面对歧义时提供有用的默认行为。

关于haskell - 为什么 3 和 x(被分配为 3)在 Haskell 中具有不同的推断类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7055146/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com