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

2023-12-13

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

考虑以下示例:

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

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

链接摘要:

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

  1. GHC 类型默认:Haskell 报告部分 4.3.4
  2. GHCi 的扩展类型默认:使用 GHCi 部分 2.4.5
  3. 单态限制:哈斯克尔 维基百科

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

let x = 5

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

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

because 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

注意多态性y = 3根据,在这些用途上有不同的专门化fromInteger相关方法提供Num实例。那是,y与特定的表示无关3,而是构建表示的方案3。天真的编译,这是缓慢的秘诀,一些人将其视为 MR 的动机。

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

当尝试学习类型系统如何工作时,将类型推断的各个方面分开确实非常有用。

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 3 和 x(被分配为 3)在 Haskell 中具有不同的推断类型? [复制] 的相关文章

  • 将数据类型设置为 Kind * -> * 这不是函子

    布伦特 约尔吉类型分类百科全书 https www haskell org haskellwiki Typeclassopedia给出以下练习 举一个类型的例子 gt 不能将其制成 的实例Functor 不使用undefined 请告诉我什
  • Haskell:无法预期类型“Integer”与实际类型“Int”

    我已经盯着这段代码有一段时间了 但我无法理解该错误消息 divisors Integer gt Integer divisors n t t lt 1 n mod n t 0 length a gt Integer length 0 len
  • 持久 selectList 导致错误“无法将类型‘BaseBackend backend0’与‘SqlBackend’匹配”

    我遇到以下编译错误 Couldn t match type BaseBackend backend0 with SqlBackend arising from a use of runSqlite The type variable bac
  • Haskell,堆栈:找到可执行文件

    我正在寻找类似的东西 stack whereis hasktags where whereis行为或多或少类似于 UNIXwhereis命令 hasktags是这样运行的 stack exec hasktags stack exec whe
  • 使用 FoldLine 解析多个块

    对于这个简化的问题 我试图解析一个如下所示的输入 foo bar baz quux woo hoo xyzzy glulx into foo bar baz quux woo hoo xyzzy glulx 我尝试过的代码如下 import
  • Haskell 中列表列表的笛卡尔积

    给定一个长度列表的列表x所有子列表的长度都相同y 输出y x长度列表x包含每个子列表中的一项 例子 x 3 y 2 1 2 3 4 5 6 Output 2 3 8不同的输出 1 3 5 1 4 5 1 3 6 1 4 6 2 3 5 2
  • Haskell 中的中缀运算符优先级

    对于以下 Haskell 表达式 返回 a gt gt f 应该读作 返回a gt gt f or 返回 a gt gt f 这里的相关规则是什么 规则始终是函数应用程序的优先级高于任何运算符 因此 return a gt gt f 被解析
  • 如何在 Haskell 中漂亮地打印表格?

    我想在 Haskell 中漂亮地打印一个类似表格的数据结构 列列表 例如 Table StrCol strings a bc c IntCol ints 1 30 2 DblCol doubles 2 0 4 5 3 2 应该渲染类似 st
  • 你能识别 Haskell 程序中的无限列表吗? [复制]

    这个问题在这里已经有答案了 可能的重复 如何判断列表是否是无限的 https stackoverflow com questions 7371730 how to tell if a list is infinite 在Haskell中 你
  • Haskell 输入返回元组

    我想知道 IO 函数是否可以返回元组 因为我想从这个函数中获取这些元组作为另一个函数的输入 investinput IO gt Char Int investinput do putStrLn Enter Username username
  • Haskell 标准库是什么?

    GHC专用库可以称为标准库吗 或者只有 Haskell 2010 报告中的那些才算数 许多 GHC 库可以通过 Haskell 报告中的函数来实现 可能与 C 绑定相结合 但其他语言依赖于 GHC 特定的扩展 因为语言报告中定义的当前 Ha
  • Data.Sequence 中的 inits 和 tails 如何工作?

    Louis Wasserman 编写了当前的实现inits and tails in Data Sequence 他表示它们非常高效 事实上 只要查看代码 我就可以看到 无论它们在做什么 它们都是以干净 自上而下的方式进行的 这往往会给惰性
  • Haskell:不在范围内:数据构造函数

    今天开始在学校学习 haskell 我遇到了函数问题 我不明白为什么它不在范围内 代码如下 ff Char gt Char gt Char ff A B x 0 y 1 x lt A y lt B x 1 y 0 和错误 md31 hs 2
  • 管道:多个流消费者

    我编写了一个程序来计算语料库中 NGram 的频率 我已经有一个函数 它消耗一串令牌并生成一个订单的 NGram ngram Monad m gt Int gt Conduit t m t trigrams ngram 3 countFre
  • 在另一个字符串中查找子字符串的索引 Haskell

    我要创建一个带有两个参数 字符串 的函数 该函数应查看第一个参数是否是第二个参数的子字符串 如果是这种情况 它将返回每个出现的元组 其中包含子字符串的起始索引和子字符串的结尾索引 例如 f String gt String gt Int I
  • 对于 Scala,“无全局类型推断”是什么意思?

    我读过 Scala 的类型推断不是全局的 因此人们必须在方法上放置类型注释 这会是 本地 类型推断吗 我只知道一点点 原因是它面向对象的本质 但我不清楚 是否有 全局类型推断 的解释以及为什么 Scala 不能让初学者可以理解 The pr
  • 在 Haskell 中获取玫瑰树的根

    最近我开始学习 Haskell 并在以下练习中遇到困难 Write functions root Rose a gt a and children Rose a gt Rose a that return the value stored
  • Haskell 项目可以使用 cmake 吗?

    我正在计划一个用 Haskell 编写的项目 也许也有一些部分是用 C 编写的 对于构建系统 我决定不选择 Haskell 程序 cabal 的常见选择 主要是因为我想了解其他语言的构建程序是如何工作的 我听说过 CMake 我认为这是一个
  • 如何同时将透镜(或任何其他光学器件)视为吸气剂和设置剂?

    我正在尝试编写一个通用记录更新程序 它允许人们轻松更新记录中的字段existing记录 字段形状相似incoming记录 这是我到目前为止所拥有的 applyUpdater fields existing incoming let gett
  • 在 Scala 中设计方便的默认值映射

    我发现自己使用了很多嵌套映射 例如 Map Int Map String Set String 并且我希望在访问新密钥时自动创建新的 Map Set 等 例如 像下面这样 val m m 1992 foo bar 请注意 如果不需要 我不想

随机推荐

  • 如何用 pandas 为空行着色并导出到 Excel 文件?

    我正在尝试在 Excel 上自动执行一些任务 其中一些包括设置没有任何红色值的单元格 我的 DataFrame 维度中的空单元格 而不是其外部的空单元格 在检查之前的类似答案后 我尝试了以下操作 import pandas as pd Cr
  • 访问动态创建的文本框文本

    我偶然发现了我的 asp net 表单的问题 在我的表单中 最终用户选择要动态创建的多个文本框 这一切都可以与以下代码配合使用 protected void txtAmountSubmit Click object sender Event
  • python ctype 初始化结构体

    我的结构包含所有 unsigned char 元素 typedef struct unsigned char bE unsigned char cH unsigned char cL unsigned char EId1 unsigned
  • 如何创建多个空数据框?

    而不是这样做 a pd DataFrame d pd DataFrame c pd DataFrame d pd DataFrame e pd DataFrame 一次 有没有一种快速方法可以用空数据框初始化所有变量 因为最终我想使用 fo
  • 使用反应扩展每秒按顺序获取下一个事件

    我有以下类型 public class NewsFeed public event EventHandler
  • 通过内置 Web 服务将文件上传到 SharePoint

    通过 WSS 3 0 版本公开的内置 Web 服务将文件上传到 SharePoint 服务器上的文档库的最佳方法是什么 根据两个最初的答案 我们肯定需要使用 Web 服务层 因为我们将从远程客户端应用程序进行这些调用 WebDAV 方法适合
  • 如何在 C# 中使工具提示指向特定标签?

    在我的应用程序中 我想使用工具提示来指向标签以引起用户的注意 toolTip IsBalloon true toolTip Show message label1 问题是气球没有指向指定的标签 我应该怎么办 这是一个已知的错误 尝试调用它两
  • 无法将焦点设置为 Chrome 扩展中的输入

    由于某种原因 我无法将焦点设置在 popup html 中的文本框上 到目前为止 这是我尝试过的 弹出 html
  • 类型名称与变量类型

    我想检查 a 的类型Variant 这是可以做到的TypeName and VarType 我想使用VarType效率更高 因为它不涉及字符串比较 仅涉及数字比较 任何偏爱的理由TypeName Public Sub testType Di
  • 指南针编译时间太长

    自从更新到最新版本的 Compass 以来 编译现在需要 4 294 秒 由于需要 我需要这个版本的指南针susy Running sass dist sass task Running watch task Completed in 4
  • 如何使用 JavaScript 发送电子邮件?

    如何使用 JavaScript 发送电子邮件 我不想使用mailto 因为如果我使用mailto 它会打开一个电子邮件客户端 做不到 发送电子邮件仅适用于服务器端 如果您所做的只是发送电子邮件 那么快速PHP脚本可能会达到目的
  • Delphi Tokyo 中不再使用 Form.PixelsPerInch

    在较旧的 Delphi 中 例如 Delphi XE4 很清楚Form PixelsPerInch财产是为了 如果我更改此属性并保存表单 关闭然后重新加载它 则表单上的所有控件和字体将相应地调整大小 然而 在德尔福东京 也许自西雅图以来 进
  • 无效的 Geojson 对象 Angularjs &Leafletjs

    在我的项目中 我尝试将过滤器与表和地图上显示的 geojson 同步 为了实现这一目标 我使用了 Angular 和以前的 Angular Leaflet Directive 但性能对于我的目的来说很慢 所以我决定为 Leaflet js
  • 如何在不同的语言环境下使用 PostgreSQL upper() 函数?

    我在共享主机上有一个 PostgreSQL 数据库 使用的结果upper由于区域设置的原因 我的本地数据库中的函数有所不同 这是我想要的 并且在我的本地环境中拥有 SELECT version PostgreSQL 8 4 16 on i3
  • Python-根据列值将数据帧拆分为多个数据帧并用这些值命名它们[重复]

    这个问题在这里已经有答案了 我有一个大型数据集 列出了在全国不同地区销售的竞争对手产品 我希望通过使用这些新数据帧名称中的列值的迭代过程 根据区域将该数据帧拆分为其他几个数据帧 以便我可以单独处理每个数据帧 例如按价格对每个地区的信息进行排
  • Python Turtle 图形键盘命令

    有人对使用键盘命令在 python 2 7 中控制海龟图形有任何见解吗 我在这个网站和其他网站上进行了广泛的研究 觉得我正在做正确的事情 但它只是不想为我工作 以下是我到目前为止所得到的 谁能告诉我哪里出错了 from turtle imp
  • Django 模板过滤器 - 一行

    我正在寻找一个 Django 模板过滤器 它将多行结构转变为一大行 有人实施过吗 原因是 我有一个表单 form as p 创建一个多行html片段 我想创建一个javascript变量 它是一个html片段 但是当我这样做时 var ne
  • 启用和禁用 gridview 上的链接按钮

    我想根据条件在 gridview 的某些行上启用或禁用链接按钮 我可以在一行上启用 linkbutton 并在同一网格视图的另一行上禁用它吗 我的代码在这里 protected void GridView1 RowDataBound obj
  • 使用 regex_search 获取所有匹配项的索引?

    我刚刚开始学习如何使用regex用于字符串处理 C 11新功能 如果以下问题太愚蠢 请原谅我 目前我应用以下代码来获取所有匹配项的索引 string str aaabxxxaab regex rx ab vector
  • 为什么 3 和 x(被分配为 3)在 Haskell 中具有不同的推断类型? [复制]

    这个问题在这里已经有答案了 Haskell 中的类型推断有一点学习曲线 至少可以这么说 开始学习它的一个好方法是通过简单的例子 因此 以下是类型推断的 hello world 考虑以下示例 Prelude gt t 3 3 Num t gt