何时需要在Haskell中输入签名? [英] When are type signatures necessary in 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屋!