How to define an existential higher kinded type in Scala

不打扰是莪最后的温柔 提交于 2019-12-19 03:24:41

问题


I was trying to define a type that accept an existential higher kinded type in Scala.

Unfortunately Scalac does not allow it.

Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_45).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :paste
// Entering paste mode (ctrl-D to finish)

trait H[F[_, _]]
trait T[A, B]
val h:H[T] = null
val e:H[F] forSome { type F[A, B] } = h

// Exiting paste mode, now interpreting.

<console>:13: error: type mismatch;
 found   : H[T]
 required: H[_[A, B] <: Any]
Note: T <: Any, but trait H is invariant in type F.
You may wish to define F as +F instead. (SLS 4.5)
       val e:H[F] forSome { type F[A, B] } = h
                                             ^

How could I workaround it?

How could I define a type that matches any H whatever the type parameter is?

Update: I even tried to let Scalac infer the existential type, still not lucky.

Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_45).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :paste
// Entering paste mode (ctrl-D to finish)

trait H[F[_, _]]
trait T[A, B]
val h:H[T] = null
trait T2[A, B]
val h2:H[T2] = null
Seq(h, h2)

// Exiting paste mode, now interpreting.

<console>:17: error: type mismatch;
 found   : H[T]
 required: H[_ >: T2 with T <: Object]
       Seq(h, h2)
           ^
<console>:17: error: type mismatch;
 found   : H[T2]
 required: H[_ >: T2 with T <: Object]
       Seq(h, h2)
              ^

回答1:


Probably sschaef is right, this is not possible. I don't know if the following helps you in any way:

type F[A,B] = X[A,B] forSome { type X[A,B] }  // alias

trait H[F[_, _]]
trait T[A, B]
val h: H[T] = null

val e: H[F] = h.asInstanceOf[H[F]]



回答2:


I found that existential higher-kinded types can be written in type patterns (and inferred from there):

def toExistential[F[_, _]](h: H[F]) = h.asInstanceOf[Any] match {
  case x: H[_] => x
}

> val h = new H[T] {}
h: H[T] = $anon$1@4d0c3eac
> val f = toExistential(h)
f: H[_] = $anon$1@4d0c3eac

The cast to Any seems to be necessary, but at least it can be encapsulated in a function.




回答3:


Instead of a type parameter you could use a type member:

trait H {
  type F[_, _]
}


来源:https://stackoverflow.com/questions/32182694/how-to-define-an-existential-higher-kinded-type-in-scala

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!