隐式转换高阶类型

时间:2017-11-14 12:40:10

标签: scala

我是斯卡拉新手......所以假设无知。

所以如果我看一下<:<

的定义

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]

想法?

1 个答案:

答案 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