scala – 没有路径的路径依赖类型?
考虑这个简单的例子:
class Outer { case class Inner() def test(i: Inner) = {} } 正如预期的那样,由于类型不匹配,因此无法编译: val o1 = new Outer() val o2 = new Outer() o1.test(o2.Inner()) // doesn't compile 如果我们想要定义一个独立的功能怎么办? 这不好 def test[X <: Outer](a: X#Inner,b: X#Inner) = {} 因为这会编译好像一切都好 test(o1.Inner(),o2.Inner()) 这有效 def test(x: Outer)(a: x.Inner,b: x.Inner) = {} 因为这编译: test(o1)(o1.Inner(),o1.Inner()) 这不是: test(o1)(o1.Inner(),o2.Inner()) 但是我们必须传递一个额外的Outer参数来测试.有可能避免这种情况吗?理想情况下,以下应该有效: test(o1.Inner(),o1.Inner()) // ok test(o1.Inner(),o2.Inner()) // compilation error 解决方法
我不认为,开箱即用,可以以令人满意的方式执行它.例如,一种可能的解决方案可能是:
scala> def test[X <: Outer#Inner](a: X)(b: X) = () test: [X <: Outer#Inner](a: X)(b: X)Unit scala> test(o1.Inner())(o1.Inner()) scala> test(o1.Inner())(o2.Inner()) <console>:16: error: type mismatch; found : o2.Inner required: o1.Inner test(o1.Inner())(o2.Inner()) ^ 看起来不错,但您可以通过显式传入类型参数来绕过它. (顺便说一句@ OlivierBlanvillain的解决方案) scala> test[Outer#Inner](o1.Inner())(o2.Inner()) 现在让我们尝试以下方法: scala> def test[X <: Outer](a: X#Inner)(b: X#Inner) = () test: [X <: Outer](a: X#Inner)(b: X#Inner)Unit scala> test(o1.Inner())(o2.Inner()) 不起作用,scalac推断X为Outer,这不够具体,我们无论如何都可以提供Outer作为显式类型参数.我们需要一种方法来强制X成为单例??类型,这样它只能表示路径o1或o2,而不是一些可以由无限量值居住的一般类型.有一种方法.为此,Scala具有标记特征Singleton.我们来试试吧: scala> def test[X <: Outer with Singleton](a: X#Inner)(b: X#Inner) = () test: [X <: Outer with Singleton](a: X#Inner)(b: X#Inner)Unit scala> test(o1.Inner())(o1.Inner()) <console>:15: error: inferred type arguments [Outer] do not conform to method test's type parameter bounds [X <: Outer with Singleton] test(o1.Inner())(o1.Inner()) ^ <console>:15: error: type mismatch; found : o1.Inner required: X#Inner test(o1.Inner())(o1.Inner()) ^ 现在我们的有效案例不再适用了!问题是scalac拒绝推断单例类型.我们必须明确地传递它们: scala> test[o1.type](o1.Inner())(o1.Inner()) 无效案例不再有效: scala> test(o1.Inner())(o2.Inner()) <console>:16: error: inferred type arguments [Outer] do not conform to method test's type parameter bounds [X <: Outer with Singleton] test(o1.Inner())(o2.Inner()) ^ <console>:16: error: type mismatch; found : o1.Inner required: X#Inner test(o1.Inner())(o2.Inner()) ^ scala> test[o1.type](o1.Inner())(o2.Inner()) <console>:16: error: type mismatch; found : o2.Inner required: o1.Inner test[o1.type](o1.Inner())(o2.Inner()) ^ scala> test[Outer](o1.Inner())(o2.Inner()) <console>:17: error: type arguments [Outer] do not conform to method test's type parameter bounds [X <: Outer with Singleton] test[Outer](o1.Inner())(o2.Inner()) ^ 所以这强制执行我们想要的规则,但你必须明确地传递类型…… 编辑 事实上,事实证明你可以强制执行此操作而不会丢失类型推断,也没有任何外部库的帮助,但你可能不会喜欢它:-p META EDIT如评论中所指出的那样,如果你努力尝试,这仍然可以规避,所以我猜你坚持上述解决方案. scala> import scala.language.existentials import scala.language.existentials scala> def test[X <: x.Inner forSome { val x: Outer }](a: X,b: X) = () test: [X <: x.Inner forSome { val x: Outer }](a: X,b: X)Unit scala> test(o1.Inner(),o1.Inner()) scala> test(o1.Inner(),o2.Inner()) <console>:16: error: inferred type arguments [Outer#Inner] do not conform to method test's type parameter bounds [X <: x.Inner forSome { val x: Outer }] test(o1.Inner(),o2.Inner()) ^ <console>:16: error: type mismatch; found : o1.Inner required: X test(o1.Inner(),o2.Inner()) ^ <console>:16: error: type mismatch; found : o2.Inner required: X test(o1.Inner(),o2.Inner()) ^ scala> test[o1.Inner](o1.Inner(),o2.Inner()) <console>:16: error: type mismatch; found : o2.Inner required: o1.Inner test[o1.Inner](o1.Inner(),o2.Inner()) ^ (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |