Haskell 什么时候需要类型签名? [英] When are type signatures necessary in Haskell?

查看:40
本文介绍了Haskell 什么时候需要类型签名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

许多介绍性文本会告诉您,在 Haskell 中,类型签名几乎总是"是可选的.有人可以量化几乎"的部分吗?

Many introductory texts will tell you that in Haskell type signatures are "almost always" optional. Can anybody quantify the "almost" part?

据我所知,您需要显式签名的唯一时候是消除类型类的歧义.(规范示例是 read . show.)还有其他我没有想到的情况吗,或者就是这样?

As far as I can tell, the only time you need an explicit signature is to disambiguate type classes. (The canonical example being read . show.) Are there other cases I haven't thought of, or is this it?

(我知道如果你在 Haskell 2010 之后有很多例外.例如,GHC 永远不会推断出 rank-N 类型.但是 rank-N 类型是一种语言扩展,而不是官方标准的一部分 [].)

(I'm aware that if you go beyond Haskell 2010 there are plenty for exceptions. For example, GHC will never infer rank-N types. But rank-N types are a language extension, not part of the official standard [yet].)

推荐答案

单态限制

如果您启用了 MonomorphismRestriction,那么有时您需要添加类型签名以获得最通用的类​​型:

Monomorphism restriction

If you have MonomorphismRestriction enabled, then sometimes you will need to add a type signature to get the most general type:

{-# LANGUAGE MonomorphismRestriction #-}
-- myPrint :: Show a => a -> IO ()
myPrint = print
main = do
  myPrint ()
  myPrint "hello"

这会失败,因为 myPrint 是单态的.您需要取消注释类型签名以使其工作,或禁用 MonomorphismRestriction.

This will fail because myPrint is monomorphic. You would need to uncomment the type signature to make it work, or disable MonomorphismRestriction.

当你把一个带有约束的多态值放入一个元组中时,元组本身就变成了多态的并且具有相同的约束:

When you put a polymorphic value with a constraint into a tuple, the tuple itself becomes polymorphic and has the same constraint:

myValue :: Read a => a
myValue = read "0"

myTuple :: Read a => (a, String)
myTuple = (myValue, "hello")

我们知道约束影响元组的第一部分,但影响第二部分.不幸的是,类型系统不知道这一点,如果您尝试这样做,它会抱怨:

We know that the constraint affects the first part of the tuple but does not affect the second part. The type system doesn't know that, unfortunately, and will complain if you try to do this:

myString = snd myTuple

尽管直觉上人们会期望 myString 只是一个 String,但类型检查器需要专门化类型变量 a 并找出是否真正满足约束.为了使这个表达式起作用,需要对 sndmyTuple 的类型进行注释:

Even though intuitively one would expect myString to be just a String, the type checker needs to specialize the type variable a and figure out whether the constraint is actually satisfied. In order to make this expression work, one would need to annotate the type of either snd or myTuple:

myString = snd (myTuple :: ((), String))

这篇关于Haskell 什么时候需要类型签名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆