Scala 是否支持类型构造函数的部分应用?

Does Scala support partial application of type constructors?

我正在从 scala-exercises 学习猫。
想知道如何使用高阶类型,有一些尝试:

 trait Functor[F[_]] {
   def map[A, B](fa: F[A])(f: A => B): F[B]
 }

 def someThingFail1[In]() = new Functor[Function1[In, _]] {
    override def map[A, B](fa: Function1[In, A])(f: A => B): Function1[In, B] = ???
  }

  def someThingFail2[In]() = new Functor[Either[In, _]] {
    override def map[A, B](fa: Either[In, A])(f: A => B): Either[In, B] = ???
  }

  def someThingFail3() = new Functor[List[_]] {
    override def map[A, B](fa: List[A])(f: A => B): List[B] = ???
  }

  //only this one can compile 
  def someThingRight1() = new Functor[List] {
    override def map[A, B](fa: List[A])(f: A => B): List[B] = ???
  }

前三个函数无法编译,错误信息如下:

[error] /Users/lorancechen/version_control_project/_tutorials/learn-cats/src/main/scala/mycats/Main.scala:16:42: Either[In, _] takes no type parameters, expected: one
[error]   def someThingFail2[In]() = new Functor[Either[In, _]] {
[error]                                          ^

为什么 Scala 不支持 type hole? Dotty 编译器会支持吗?谢谢

那是因为

Either[X, _]

存在类型,可以显式写成

Either[X, Y] forSome { type Y }

这有点类似于 Java 的通配符,而不是您想要作为高阶 Functor 类型构造函数的参数。您想要的是 类型的 lambda。本来可以这么写的:

({type lam[Y] = Either[X, Y]})#lam

lambda 类型完全可以在 Scala 中使用这一事实并不是计划中的功能,而是一个 accidental discovery, and the syntax was somewhat lengthy. However, there is the non/kind-projector 插件可以显着简化它。使用此插件,您的代码将变为:

trait Functor[F[_]] {
  def map[A, B](fa: F[A])(f: A => B): F[B]
}

def someThingFail1[In]() = new Functor[Function1[In, ?]] {
  override def map[A, B](fa: Function1[In, A])(f: A => B): Function1[In, B] = ???
}

def someThingFail2[In]() = new Functor[Either[In, ?]] {
  override def map[A, B](fa: Either[In, A])(f: A => B): Either[In, B] = ???
}

def someThingFail3() = new Functor[List[?]] {
  override def map[A, B](fa: List[A])(f: A => B): List[B] = ???
}

//only this one can compile 
def someThingRight1() = new Functor[List] {
  override def map[A, B](fa: List[A])(f: A => B): List[B] = ???
}

(使用 scala 2.12.4、cats 1.0.1、kind-projector 0.9.4 测试)。

注意这个插件is used in cats source code(搜索?)。

一切都会在dotty变得更好,它already supports a neat syntax for type lambdas