Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 类型神秘。这段代码为什么要编译?_Haskell_Polymorphism_Type Inference_Ambiguity - Fatal编程技术网

Haskell 类型神秘。这段代码为什么要编译?

Haskell 类型神秘。这段代码为什么要编译?,haskell,polymorphism,type-inference,ambiguity,Haskell,Polymorphism,Type Inference,Ambiguity,代码 default () h :: Bool h = 1.0 == 1.0 --Error. Ambiguity. 不编译。这是意料之中的,因为存在歧义。它可以是Float或Double,Haskell不知道我们想要哪一个 但是代码 default () foo :: (Fractional a, Eq a) => a -> Bool foo x = x == 1.0 编译成功。我不完全明白为什么。为什么这不也是模棱两可的 我觉得这是因为无论何时我们调用foo,我们都保证选择了

代码

default ()
h :: Bool
h = 1.0 == 1.0 --Error. Ambiguity.
不编译。这是意料之中的,因为存在歧义。它可以是
Float
Double
,Haskell不知道我们想要哪一个

但是代码

default ()
foo :: (Fractional a, Eq a) => a -> Bool
foo x = x == 1.0
编译成功。我不完全明白为什么。为什么这不也是模棱两可的

我觉得这是因为无论何时我们调用
foo
,我们都保证选择了一种具体类型来代替
a
,也就是说,我们保证将
a
固定为
Float
Double
(或者我们的自定义类型在编译时同时具有
分数
Eq
)的实例,因此不存在歧义


但这只是一种感觉,我不知道它是否100%准确。

本文中对歧义的定义如下:

我们说一个表达式
e
有一个不明确的类型,如果在它的类型
forall.cx=>t
中,在
us
中有一个类型变量
u
,它出现在
cx
中,但不出现在
t
中。这种类型是无效的

foo::(分数a,等式a)=>a->Bool
中没有这样的变量(因为
a
出现在
a->Bool
中)。在
1.0==1.0
中,类型实际上是
(分数a,等式a)=>Bool
,因此存在这样的变量


这种歧义之所以是错误的,是因为编译器无法在变量
a
的不同实例化之间进行选择,并且程序的结果可能取决于它选择的实例化。在这种情况下,对于任何合理的实例化,
1.0==1.0
应始终为
True
,但1)编译器不知道这一点;2) 并非所有的实例化都是合理的

第二段代码编译是因为

foo :: (Fractional a, Eq a) => a -> Bool
foo x = x == 1.0

(==) :: Eq a => a -> a
因此,编译器将知道浮点数文本
1.0::Rational a=>a
x
具有相同的类型,后者具有
Eq
实例,即此函数中
==
的“含义”对于每个调用都是确定的


而在第一段代码中,文字可以是任何类型的
(有理a,等式a)=>a
,因此
==
的“含义”是不明确的,h的值可以是真的也可以是假的,取决于文字的类型,这是没有提供的。

这里有另一种概念性的说法:

这两种情况都有内在的歧义,但第一种情况是死路一条——编译器没有希望推断出摆脱歧义的方法

第二种情况也是不明确的,但不明确是公开的——无论谁调用不明确的代码,都必须解决不明确的问题,或者在调用堆栈中进一步委托/冒泡它


这就是它的全部——多态性是受控的模糊性。第一种情况是不受控制的歧义,因此它不是有用的(即多态性相关的)歧义。所以它会被拒绝,直到它被注释为明确无误

@Carsten两者都在
Eq
,这一点都不重要;这是非法的,因为选择其中一个可能会给出与另一个不同的结果(对于这个程序,它当然不会,但编译器不知道,也不应该知道)。@AlexeyRomanov很抱歉……你能仔细地说一下为什么这不是一个复制的吗?