如何在 Scala 中定义一个存在的更高种类的类型
Posted
技术标签:
【中文标题】如何在 Scala 中定义一个存在的更高种类的类型【英文标题】:How to define an existential higher kinded type in Scala 【发布时间】:2015-11-17 21:35:47 【问题描述】:我试图在 Scala 中定义一个接受存在的更高种类类型的类型。
不幸的是 Scalac 不允许这样做。
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
^
我该如何解决?
无论类型参数是什么,我如何定义一个匹配任何H
的类型?
更新:我什至试图让 Scalac 推断存在类型,但仍然不幸运。
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)
^
【问题讨论】:
我不认为你可以。见***.com/questions/3122398/… 这是奇怪的事情:使H
在F
(trait H[+F[_, _]]
) 中协变,突然以下编译正常:val h2:H[Any] = null
。是的,Any
就在那里,这里需要一个 constructor 类型。如果有人知道这是否是故意的(如果是的话,这是什么意思)我想知道。
@RégisJean-Gilles 我猜这是一个 scalac 错误
我也敢打赌,但欢迎发表权威声明。
@sschaef 这个限制似乎在 Scala 2.11 中被移除了。
【参考方案1】:
可能 sschaef 是对的,这是不可能的。我不知道以下内容是否对您有任何帮助:
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】:我发现存在的更高种类的类型可以写成类型模式(并从那里推断):
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
Any
的强制转换似乎是必要的,但至少它可以封装在一个函数中。
【讨论】:
【参考方案3】:您可以使用类型成员来代替类型参数:
trait H
type F[_, _]
【讨论】:
以上是关于如何在 Scala 中定义一个存在的更高种类的类型的主要内容,如果未能解决你的问题,请参考以下文章