为什么这会无效使用Scala的抽象类型? [英] Why is this an invalid use of Scala's abstract types?
问题描述
我有此代码:
class A extends Testable { type Self <: A }
class B extends A { type Self <: B }
trait Testable {
type Self
def test[T <: Self] = {}
}
object Main {
val h = new A
// this throws an error
h.test[B]
}
我的错误是:
error: type arguments [B] do not conform to method test's type parameter bounds [T <: Main.h.Self]
h.test[B]
在这个问题中,这是由于路径相关的类型.任何人都可以弄清楚如何拥有T< ;: Self,而不会遇到依赖于路径的类型问题吗?
任何帮助将不胜感激.
您的代码必须像这样:
// --- fictional scala syntax ---
class A extends Testable { type Self = A }
class B extends A { override type Self = B }
但是在当前版本的scala中,它不可能.
我会提出一些建议(不超过使用依赖路径的类型,而是另一种),它符合您的要求.
a)使用Type-class模式作为测试方法;
b)使用隐式参数来符合类型关系.
类层次结构:
trait Testable
class A extends Testable
class B extends A
符合特征:
trait Conforms[X, Y]
可测试的类型类:
object TestableTypeClass {
implicit def testMethod[T <: Testable](testable : T) = new {
def test[X](implicit ev : Conforms[X, T]) = {}
}
}
伴随对象中的
test
方法类型参数条件:
object A {
// P <: A is your conditon (Self <: A) for class A
implicit def r[P <: A] = new Conforms[P , A] {}
}
object B {
// P <: B is your conditon (Self <: B) for class B
implicit def r[P <: B] = new Conforms[P , B] {}
}
测试:
import TestableTypeClass._
val a = new A
a.test[A] // - Ok
a.test[B] // - Ok
val b = new B
// b.test[A] // - did not compile
b.test[B] // - Ok
更新:
1)可以在一个对象中收集所有隐式对象,在这种情况下,需要导入具有隐式对象的对象(之前在伴随对象中隐式范围的规则不需要该对象):
object ImplicitContainer {
implicit def r1[P <: A] = new Conforms[P , A] {}
implicit def r2[P <: B] = new Conforms[P , B] {}
}
并使用:
import TestableTypeClass._
import ImplicitContainer._
val a = new A
a.test[A]
a.test[B]
2,3)为2类型参数X
& Y
X-用于将来的类型约束(此约束来自参数方法)
Y-用于确定将为其定义类型约束的类型
根据Comforms
实例类型隐式选择参数,并且这种设计的想法是结合使用X&是
TestableTypeClass
中的类型Y,是通过 一个主要特征是 为了更好地理解,又给出了一个具有更严格规则的示例: I have this code: And my error is: On this question, it was said that this was due to path dependent types. Can anyone figure out how to have T <: Self, without having the path-dependent types problem? Any help would be appreciated. Your code need to be looks like: But it is imposible in current version of scala. I would propose little bit long way (not longer than using path dependent types but another), and it conforms your requirements. a) Use Type-class pattern for test method; b) Use implicit parameters for conforms type relations. Class hierarchy: Conforms trait: Testable Type-class: Tests: UPDATE: 1) It is possible to collect all implicits in one object, and in this case object with implicits need to import (it is not needed before by rules of implicit scope in companion object): and using: 2,3) trait X - used for future type constraint (and this constraint come from parametric method) Y - used for determine the type for which will be define type constraint implicit parameter choise by in Type-class And a main feature is invariance of And for better understanding, one more example with more strict rules:
这篇关于为什么这会无效使用Scala的抽象类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!test
方法从Testable
隐式转换为匿名类而捕获的Y类型,而类型Conforms
特征的不变性,这就是为什么隐式函数不是模棱两可并正确管理绑定规则的原因. //...
class C extends B
object ImplicitContainer {
implicit def r1[P <: A] = new Conforms[P , A] {}
implicit def r2[P](implicit ev : P =:= B) = new Conforms[P , B] {}
implicit def r3[P <: C] = new Conforms[P , C] {}
}
import TestableTypeClass._
import ImplicitContainer._
val b = new B
//b.test[A] // - did not compile
b.test[B] // - Ok
//b.test[C] // - did not compile
class A extends Testable { type Self <: A }
class B extends A { type Self <: B }
trait Testable {
type Self
def test[T <: Self] = {}
}
object Main {
val h = new A
// this throws an error
h.test[B]
}
error: type arguments [B] do not conform to method test's type parameter bounds [T <: Main.h.Self]
h.test[B]
// --- fictional scala syntax ---
class A extends Testable { type Self = A }
class B extends A { override type Self = B }
trait Testable
class A extends Testable
class B extends A
trait Conforms[X, Y]
object TestableTypeClass {
implicit def testMethod[T <: Testable](testable : T) = new {
def test[X](implicit ev : Conforms[X, T]) = {}
}
}
test
method type parameter conditions in companion objects:object A {
// P <: A is your conditon (Self <: A) for class A
implicit def r[P <: A] = new Conforms[P , A] {}
}
object B {
// P <: B is your conditon (Self <: B) for class B
implicit def r[P <: B] = new Conforms[P , B] {}
}
import TestableTypeClass._
val a = new A
a.test[A] // - Ok
a.test[B] // - Ok
val b = new B
// b.test[A] // - did not compile
b.test[B] // - Ok
object ImplicitContainer {
implicit def r1[P <: A] = new Conforms[P , A] {}
implicit def r2[P <: B] = new Conforms[P , B] {}
}
import TestableTypeClass._
import ImplicitContainer._
val a = new A
a.test[A]
a.test[B]
Conforms
defined for 2 type parameter X
& Y
Comforms
instance type, and idea of this design is playing with combinations X & YTestableTypeClass
type Y captured by implicit conversion from Testable
to anonimous class with test
method, and type X captured in test
method call.Conforms
trait, this is why implicits is not ambiguous and correctly manage bound rules. //...
class C extends B
object ImplicitContainer {
implicit def r1[P <: A] = new Conforms[P , A] {}
implicit def r2[P](implicit ev : P =:= B) = new Conforms[P , B] {}
implicit def r3[P <: C] = new Conforms[P , C] {}
}
import TestableTypeClass._
import ImplicitContainer._
val b = new B
//b.test[A] // - did not compile
b.test[B] // - Ok
//b.test[C] // - did not compile