什么是 ? 类型?

7

我正在尝试为一个具有多个类型参数的类型实现cats Monad实例。我查看了cats Either实例,以了解如何在那里完成。下面是从cats中复制的EitherMonad实例代码的一部分:

import cats.Monad

object EitherMonad {
  implicit def instance[A]: Monad[Either[A, ?]] =
    new Monad[Either[A, ?]] {
      def pure[B](b: B): Either[A, B] = Right(b)

      def flatMap[B, C](fa: Either[A, B])(f: B => Either[A, C]): Either[A, C] =
        fa.right.flatMap(f)
    }
}

它无法编译并出现错误:error: not found: type ? 当我为自己的类型创建实例时,?类型是什么,我该如何使用它?

1
“?”是一个有效的符号,就像在这种情况下的“A”一样。 - Matt Ball
1个回答

10

这是所谓的类型λ表达式的特殊语法,由kind projector插件添加。

Either[A, ?]

是的,它是一个快捷方式。

({type L[X] = Either[A, X]})#L
整段代码的展开形式是:
import cats.Monad

object EitherMonad {
  implicit def instance[A]: Monad[({type L[X] = Either[A, X]})#L] = new Monad[({type L[X] = Either[A, X]})#L] {
    def pure[B](b: B): Either[A, B] = Right(b)

    def flatMap[B, C](fa: Either[A, B])(f: B => Either[A, C]): Either[A, C] =
      fa.right.flatMap(f)
  }
}

类型λ(type lambdas)看起来很吓人,但它本质上是一个非常简单的概念。假设你有一个需要两个类型参数的东西,比如Either[A, B]。你想为Either提供一个monad实例,但是trait Monad[F[_]]只接受一个类型参数。但原则上没问题,因为你的monad实例只关心第二个("右边")类型参数。类型λ只是一种方式来“修复”第一个类型参数,以便你拥有正确的形状。

如果你在值级别上做同样的事情,你甚至不用多想。你得到了一个两个参数的函数。

val f: (Int, Int) => Int = ...

你需要将某些东西传递给函数 f,该函数仅接受 1 个参数。

def foo(x: Int => Int) = ...

使事情合适的唯一方法是修复其中一个参数。

foo(x => f(1, x))

这正是类型 lambda 在类型层面上所做的事情。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接