可能有人请解释为什么这编译设置类型为NUM
Prelude> 1 :: Num a => a
这并不
Prelude> 1.0 :: Num a => a
第二个例子将与Fractional
工作,但Num
是Fractional
超。就像它的超类Integral
。
可能有人请解释为什么这编译设置类型为NUM
Prelude> 1 :: Num a => a
这并不
Prelude> 1.0 :: Num a => a
第二个例子将与Fractional
工作,但Num
是Fractional
超。就像它的超类Integral
。
如果我们有
x :: Num a => a
的x
用户可以选择a
通缉。例如。
x :: Int
如果x = 1.5
不适用?
因为这个原因浮点文字不能给多态类型Num a => a
,因为它的值不会(通常)适合所有类型的所有Num
。
积分文字适合每种数字类型,因此它们是允许的。
类型类之间的超类关系确实是而不是在类型之间建立关系。它告诉我们,只有,如果类型T是类型类Ç的一员,并乙是一个超类的Ç,然后吨也将乙的成员。
它不说每个值v ::吨可以在任何类型的,这也是乙的构件使用。但这就是你要说的:
3.14159 :: Num a => a
区分OO语言中的多态和Haskell中的多态是很重要的。 OO polymorphism is covariant, while Haskell's parametric polymorphism is contravariant。
这意味着:在面向对象的语言,如果你有
class A {...}
class B: A {...}
即A
是B
一个超类,然后B
类型的任何值也A
类型的值。 (请注意,任何特定的值其实并不多态的,但有一个具体的类型!)因此,如果你有
class Num {...}
class Fractional: Num {...}
那么Fractional
值确实可以被用作Num
值。这大致是协变意味着什么:任何子类值is also a superclass value;值的层次结构与类型层次结构相同。
在Haskell中,class
es是不同的。没有“Num
类型的值”这样的东西,只有具体类型的值a
。 类型可能在Num
类。
不像在面向对象的语言,如1 :: Num a => a
值为多态:它可以在任何类型的环境的需求,提供的类型在Num
类。 (其实这句法只是缩写1 :: ∀ a . Num a => a
,将被解读为“为所有类型的a
,你可以有a
类型的值1
。)例如,
Prelude> let x = 1 :: Num a => a
Prelude> x :: Int
1
Prelude> x :: Double
1.0
你也可以给x
更具体的约束Fractional
,因为这是Num
的一个子类。这只是限制什么类型的多态值可以被实例:
Prelude> let x = 1 :: Fractional a => a
Prelude> x :: Int
<interactive>:6:1:
No instance for (Fractional Int) arising from a use of ‘x’
...
Prelude> x :: Double
1.0
因为Int
不是小数类型。因此,Haskell的多态性是逆变的:限于超类的多态值也可以被限制到一个子类,而不是相反的方式。具体而言,可以很明显的有
Prelude> let y = 1.0 :: Fractional a => a
(y
相同x'
),但你不能一概而论这y' = 1.0 :: Num a => a
。 Ingo评论说这是一件好事,否则将有可能做
Prelude> 3.14159 :: Int
????
明白了。 num不是类似于oo的类型,而是一组类型,为了val是多态的,它必须能够实例化为任何num类型,任何其他规则都会导致荒谬的情况,正如你们所展示的那样。 – rodic
谢谢@chi。当你这样做时有意义:)所以'1 :: Num a => a'适用于任何'Num'实例的'a',但'1.0'不适用。 – rodic
@rodic是的。从理论上讲,Haskell的设计者可能已经强制要求'1.0'被当作'1'来处理,但实际上,发现在给定的上下文中'1.0'类型检查但是'1.5'确实会引起混乱不。因此,只允许使用'1.0'来代表'Fractional'类型中的类型值。 – chi
是的,当我写1.0时,我有任何想法。但现在我意识到我的原始问题可以重写,为什么'1 :: a'不能编译。非常感谢您的帮助。 – rodic