首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么在Haskell中不能推断多态值?

为什么在Haskell中不能推断多态值?
EN

Stack Overflow用户
提问于 2010-11-15 04:13:46
回答 2查看 1.4K关注 0票数 22

数值型文字具有多态类型:

代码语言:javascript
复制
*Main> :t 3
3 :: (Num t) => t

但是如果我将一个变量绑定到这样的文字,多态性就会丢失:

代码语言:javascript
复制
x = 3
...
*Main> :t x
x :: Integer

另一方面,如果我定义一个函数,它当然是多态的:

代码语言:javascript
复制
f x = 3
...
*Main> :t f
f :: (Num t1) => t -> t1

我可以提供一个类型签名来确保x保持多态:

代码语言:javascript
复制
x :: Num a => a
x = 3
...
*Main> :t x
x :: (Num a) => a

但是为什么这是必要的呢?为什么不推断多态类型?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-11-15 04:24:35

它是monomorphism restriction,它规定所有没有参数和没有显式类型注释的值都应该有一个单态类型。可以使用-XNoMonomorphismRestriction在ghc和ghci中禁用此限制。

限制的原因是,如果没有这个限制,long_calculation 42将被评估两次,而大多数人可能希望/希望它只评估一次:

代码语言:javascript
复制
longCalculation :: Num a => a -> a
longCalculation = ...

x = longCalculation 42

main = print $ x + x
票数 23
EN

Stack Overflow用户

发布于 2010-11-15 06:17:42

在Sepp2k的答案上进行一点扩展:如果您尝试编译以下代码(或将其加载到GHCi中),则会得到一个错误:

代码语言:javascript
复制
import Data.List (sort)
f = head . sort

这违反了单态限制,因为我们有一个类约束(由sort引入),但是没有显式的参数:我们(有点神秘地)被告知在约束Ord a中有一个Ambiguous type variable

您的示例(let x = 3)有一个类似的二义性类型变量,但它不会产生相同的错误,因为它是由Haskell's "defaulting" rules保存的

当整个模块的类型推断完成时,剩下的任何单态类型变量都被认为是不明确的,并使用默认规则解析为特定的类型(第4.3.4节)。

有关缺省规则的更多信息,请参见this answer -重要的一点是,它们只适用于某些数值类,所以x = 3是可以的,而f = sort则不是。

附注:如果您希望x = 3最终成为Int而不是Integer,并且y = 3.0成为Rational而不是Double,您可以使用“默认声明”来覆盖默认的默认规则:

代码语言:javascript
复制
default (Int, Rational)
票数 19
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4179453

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档