我是斯卡拉新手......所以假设无知。
所以如果我看一下<:<
的定义 sealed abstract class <:<[-From, +To] extends (From => To)
implicit def conforms[A]: A <:< A = new (A <:< A) {def apply(x: A) = x}
这用于定义类型A是B的子类型的证据。
A&lt;:B
......但如果我想要证据那该怎么办?
forall T. A [T]&lt ;: B [T]
好吧....所以我尝试遵循相同的食谱
abstract class Foo[-A[_],+B[_]] { def apply[C](x : A[C]) : B[C] }
implicit def conforms[A[_]] : Foo[A,A] = new Foo[A,A] { def apply[C](x : A[C]) : A[C] = x }
我可以使用此约束手动应用转换,但我无法让编译器隐式“应用”它。 (因为它没有扩展A =&gt; B?)
所以例如,如果我定义;
abstract class FooInt[-A[_],+B[_]] extends (A[Int] => B[Int])
implicit def conformsInt[A[Int]] : FooInt[A,A] = new FooInt[A,A] { def apply(x : A[Int]) : A[Int] = x }
然后编译器将自动将转换应用于类型A [Int]
的值我只想将其概括为A [T]
想法?
答案 0 :(得分:0)
sealed abstract class <:<
- 这告诉你不能构建“新证据”。您必须依赖编译器确认两个现有类型确实符合现有证据。这应该适用于所有类型,如果没有,你试图证明错误的东西。
您声明要证明A[T] <: B[T] forAll { type T }
。这取决于A和B的类型参数的方差。如果您想忽略该参数,则只能询问证据A[_] <:< B[_]
。 E.g。
trait Animal; trait Cat extends Animal
trait Foo[A]
trait Bar[A] extends Foo[A]
implicitly[Bar[Cat] <:< Foo[Cat]] // ok, A is fixed
implicitly[Bar[Cat] <:< Foo[Animal]] // not possible
implicitly[Bar[Animal] <:< Foo[Cat]] // not possible
implicitly[Bar[_] <:< Foo[_]] // ok, we forget about A
如果您有差异,可以保留A:
trait Breeds[+A] // covariant, can "produce" A
trait Feeds [-A] // contravariant, can "consume" A
class Baz[A] extends Breeds[A] with Feeds[A]
implicitly[Baz[Cat] <:< Feeds[Animal]] // nope
implicitly[Baz[Animal] <:< Feeds[Cat]] // ok
implicitly[Baz[Cat] <:< Breeds[Animal]] // ok
implicitly[Baz[Animal] <:< Breeds[Cat]] // nope