使用匿名函数创建 FunctionK 实例

问题描述 投票:0回答:1

我想创建一个具有匿名函数的

FunctionK
实例。这是最小的例子:

import cats.~>

given (Option ~> List) = {
  case Some(a) => a :: Nil
  case None    => Nil
}

但是,此代码片段会引发编译错误:

Missing parameter type

I could not infer the type of the parameter x$1
in expanded function:
  x$1 =>
  x$1 match 
    {
      case Some(a) =>
        a :: Nil
      case None =>
        Nil
    }
Expected type for the whole anonymous function:
  cats.arrow.FunctionK[Option, List]

编译器不够智能,无法推断所有类型,还是我使用匿名函数的方式不正确?

Scala==3.4.0-RC1
cats.core==2.10.0

编译
scala scala-cats
1个回答
0
投票

我们来一步步分析吧。

FunctionK
实际上不是一个函数。在仅限 Scala 3 的世界中,它可以定义为:

type FunctionK[F[_], G[_]] = [A] => F[A] => F[G]

这将使其成为多态函数类型。但它是在 Scala 3 成为现实之前定义的,并且需要与旧的表示向后兼容,它:

trait FunctionK[F[_], G[_]] {

  def apply[A](fa: F[A]): G[A]
}

这是 Scala 2 针对没有多态函数类型的解决方法。

在以下情况下:

trait FunctionLike[A, B] {

  def method(a: A): B
}

val fl: FunctionLike[Int, String] = _.toString

我们正在使用单一抽象方法语法 - 编译器发现我们在可以使用

new FunctionLike[Int, String] { ... }
的地方使用 lambda 语法,但它也看到这个
trait
/
abstract class
只有 1 个抽象方法,因此它可以假设我们想通过实现这个方法来实现整个
trait
/
abstract class

事实是,SAM 目前似乎仅针对普通(单态)方法实现,当您将 lambda 用于多态方法时,它不会建立连接:

import cats.~>

given (Option ~> List) = [A] => (opt: Option[A]) => opt match {
  case Some(a) => a :: Nil
  case None    => Nil
}
// error:
// Found:    [A] => (opt: Option[A]) => List[A]
// Required: cats.arrow.FunctionK[Option, List]

在您的情况下,您还使用了单态函数类型的语法:当前,当您需要多态函数类型时,您必须编写:

[A] => (a: A) => ...
- 类型参数必须显式定义并在参数之一中显式使用。

© www.soinside.com 2019 - 2024. All rights reserved.