如何在 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/… 这是奇怪的事情:使HF (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 中定义一个存在的更高种类的类型的主要内容,如果未能解决你的问题,请参考以下文章

为更高种类的数据派生实例

如何表达更高种类类型的类型约束

为啥物化泛型很难与更高种类的类型结合?

20个让你效率变的更高的CSS代码小技巧!

自适应布局中更大 iPhone 的更高约束乘数

Scala之Object (apply) dycopy