【问题标题】:Distinction between type aliases and type lambdas类型别名和类型 lambda 之间的区别
【发布时间】:2012-12-09 09:57:53
【问题描述】:

这个问题是关于 Scala 隐式解析系统的限制,我在使用 Scalaz 时遇到过几次,这对我来说没有多大意义。我已将问题提炼为下面的无 Scalaz 版本,但如果需要,我很乐意提供有关动机的更多信息。

假设我有几个类型类见证了类型构造函数:

import scala.language.higherKinds

trait Foo[F[_]]
trait Bar[F[_], A]

现在还假设,如果我有一些 FFoo 实例,我知道我也有 Bar[F, _]Foo 实例:

implicit def barFoo[F[_]: Foo] = new Foo[({type L[X] = Bar[F, X]})#L] {}

我还有ListEither 右侧的实例:

implicit object listFoo extends Foo[List]
implicit def eitherFoo[A] = new Foo[({type L[X] = Either[A, X]})#L] {}

现在很明显,我应该能够编写以下内容:

type BarList[X] = Bar[List, X]

implicitly[Foo[BarList]]

或者,等效地:

implicitly[Foo[({type L[X] = Bar[List, X]})#L]]

确实,两者都按预期工作。

所以我尝试以下方法:

type StringOr[X] = Either[String, X]
type BarStringOr[X] = Bar[StringOr, X]

然后:

scala> implicitly[Foo[BarStringOr]]
res2: Foo[BarStringOr] = $anon$1@39a6c855

同样,这里没有惊喜。但后来我尝试:

implicitly[Foo[({type L[X] = Bar[StringOr, X]})#L]]

我得到以下信息:

<console>:15: error: could not find implicit value for parameter e: Foo[[X]Bar[[X]scala.util.Either[String,X],X]]
              implicitly[Foo[({type L[X] = Bar[StringOr, X]})#L]]
                        ^

请注意,我可以毫无问题地为StringOr 推断必要的Foo 实例,或者显式调用barFoo 以获得所需的实例:

scala> implicitly[Foo[StringOr]]
res4: Foo[StringOr] = $anon$1@3eaac006

scala> barFoo[StringOr]
res5: Foo[[X]Bar[StringOr,X]] = $anon$1@179fbfea

我无法确定 ListStringOr 案例之间可能存在的重要区别,即允许类型 lambda 版本适用于前者但不适用于后者。

我已经在 Scala 2.10.0-RC5 和 2.9.2 上尝试过这个。在整个过程中添加协方差并没有帮助。

我是否遗漏了一些明显的东西?有人可以指出规范中的某些内容,以帮助我理解这一点,或者指向以前对类似问题的讨论吗?

【问题讨论】:

标签: scala types scalaz implicits


【解决方案1】:

好的,我不是 100% 确定,但我认为我们可以通过将其减少到可能失败的最简单情况来取得一些进展。隐式不是这里的问题,类型别名也不是。这足以失败:

trait Foo[F[_]]
trait Bar[F[_], A]

def barFoo[F[_]: Foo] = new Foo[({type L[X] = Bar[F, X]})#L] {}

val res1: Foo[({type L[X] = Either[String, X]})#L] = null

val works = barFoo[({type L[X] = Either[String, X]})#L](res1)
val fails = barFoo(res1)

问题在于 Scala 无法将 barFoo 的类型参数推断为 [X]Either[java.lang.String,X]。这似乎是由于(或至少与)scalac's refusal to infer a partially applied type constructor.

(在相关说明中,这是 Scala 认为复杂到无法接受的类型之一)。

【讨论】:

    猜你喜欢
    • 2013-11-17
    • 2021-01-12
    • 2013-08-19
    • 2013-10-05
    • 2016-09-28
    • 2013-05-19
    • 1970-01-01
    • 1970-01-01
    • 2015-11-07
    相关资源
    最近更新 更多