何时需要在Haskell中输入签名? [英] When are type signatures necessary in Haskell?

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

问题描述

许多介绍性文本都会告诉你,在Haskell中,类型签名几乎总是可选的。任何人都可以量化几乎的部分吗?



据我所知,只需要时间您需要明确的签名是为了消除类型的歧义类。 (典型示例是 read。show 。)是否还有其他我没有想到的情况,或者是这个情况?



(我知道,如果超越Haskell 2010,有很多例外,例如,GHC永远不会推断rank-N类型,但是rank-N类型是语言扩展,不是官方标准的一部分)

MonomorphismRestriction 已启用,则有时您需要添加类型签名才能获得最常用的类型:

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

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



幻影约束



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

  myValue :: Read a => a 
myValue =读取0

myTuple ::读取a => (a,String)
myTuple =(myValue,hello)

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

  myString = snd myTuple 

即使直观地看到 myString 是只需一个 String ,类型检查器需要来专门化类型变量 a 并找出结果约束是否实际满足。为了使这个表达式有效,我们需要注释 snd myTuple 的类型:

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


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

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?

(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].)

解决方案

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"

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

Phantom constraints

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

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天全站免登陆