Scala是否在隐式存在的情况下保证连贯性?

时间:2019-03-02 01:05:51

标签: scala implicit type-systems

文章Type classes: confluence, coherence and global uniqueness提出以下几点-

  

[Coherence]指出,程序的每一个不同的有效类型派生都会导致所产生的程序具有相同的动态语义。

     

[..]

     

那么,当人们将Scala类型类与Haskell类型类进行比较时,人们常指的是什么?我将其称为实例的全局唯一性,定义为:在完全编译的程序中,对于任何类型,给定类型类最多具有一个实例解析。具有局部类型类实例的语言(例如Scala)通常不具有此属性,但是在Haskell中,我们发现该属性在构建集等抽象时非常方便。

如果您在Modular implicits上查看此论文,则说明-

  

[..] Scala的连贯性可以依靠非歧义性的弱点   而不是经典。这意味着您可以定义多个Showable [Int]类型的隐式对象。   在您的程序中而不会导致错误。相反,如果隐式解决方案,Scala会发出错误   参数不明确。例如,如果范围为Showable [Int]的两个隐式对象在范围内,则当   将show应用于Int时,编译器将报告歧义错误。

这两者给人的印象是Scala确实可以确保一致性,但不能确保实例的全局唯一性。

但是,如果您查看马丁·奥德斯基(Martin Odersky)的评论(12),似乎术语“一致性”被用作“实例唯一性”的简写,这将解释术语“局部一致性”和“全局一致性”。

  1. 这是否只是不幸的情况,同一术语用于表示两个不同的事物?它们肯定是不同的-OCaml的模块化隐式确保一致性(按照第一个定义),但不能确保实例的全局唯一性。

  2. Scala是否在隐式存在的情况下保证一致性(按照第一个定义)?

1 个答案:

答案 0 :(得分:1)

在这种情况下,我认为它们的意思相同。仅当您拥有不止一种推导实例/隐式值的方法时,才会考虑一致性。仅当 不止一次时,“每个不同的有效类型推导”才有意义。 Scala和Haskell都不允许在编译时实例,这可能导致模棱两可的推导。

Scala

Odersky的评论对Scala来说就是这样:只有一种 local 解决实例的方法。换句话说,只有一个有效的本地类型推导。琐碎地讲,它本身就是连贯的。对我来说尚不清楚,谈论Scala中的全球一致性甚至是有意义的,但是,如果确实如此,那么Scala肯定没有:

object Object1 {
  implicit val i: Int  = 9
  println(implicitly[Int])    // valid typing derivation of `Int` => printing 9
}
object Object2 {
  implicit val i: Int  = 10
  println(implicitly[Int])    // valid typing derivation of `Int` => printing 10
}

Haskell

由于Haskell实例是全局实例,因此无法区分本地/全局一致性。

Haskell在编译时不允许有两个实例,其中一个实例头与另一个实例头重叠。这将查找类型推导变成明确的非回溯搜索问题。无歧义再次使我们保持一致。

足够有趣的是,GHC允许您使用-XIncoherentInstances放宽此要求,允许您编写本地非融合实例,也有可能破坏全局一致性。