【问题标题】:How to define an existential higher kinded type in Scala如何在 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)
              ^

【问题讨论】:

  • 我不认为你可以。见stackoverflow.com/questions/3122398/…
  • 这是奇怪的事情:使HF (trait H[+F[_, _]]) 中协变,突然以下编译正常:val h2:H[Any] = null。是的,Any 就在那里,这里需要一个 constructor 类型。如果有人知道这是否是故意的(如果是的话,这是什么意思)我想知道。
  • @RégisJean-Gilles 我猜这是一个 scalac 错误
  • 我也敢打赌,但欢迎发表权威声明。
  • @sschaef 这个限制似乎在 Scala 2.11 中被移除了。

标签: scala functional-programming type-systems existential-type higher-kinded-types


【解决方案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[_, _]
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多