scala - 如何在 Scala 中扩展函数类

标签 scala function inheritance functional-programming extending-classes

我是 Scala 新手。 我有一个 A 类,它扩展了 C 类。我还有一个 B 类,它也扩展 C 类

我希望 A->B 类型的函数对象也扩展 C(以及其他派生类型,例如 A->(A->B))。但我在“Scala 编程”中读到了以下内容:

A function literal is compiled into a class that when instantiated at runtime is a function value.

是否有某种方法可以自动让 A->B extend C,而不需要手动创建一个代表功能?

最佳答案

Scala 中的函数是通过 FunctionN 特征建模的。例如,简单的一输入一输出函数都是以下特征的实例:

trait Function1[-T1, +R] extends AnyRef

所以你问的是“如何使 Function 的实例也成为 C 的子类”。这无法通过标准子类型/继承来实现,因为显然我们无法修改 Function1 特征以使其扩展您的自定义类 C。当然,我们可以按照您的建议创建一个新类来表示该函数,但这只会让我们到目前为止,并且实现起来并不容易,更不用说您想要用作 C 的任何函数了code> 必须首先转换为您的伪函数特征,这将使事情变得可怕。

但是,我们可以做的是创建一个类型类,其中包含 A -> B 等的实现。

我们以下面的代码为例:

trait A
trait B
trait C[T]

object C {
  implicit val fa = new C[A] {}
  implicit val fb = new C[B] {}
  implicit val fab = new C[Function1[A, B]] {}
}


object Test extends scala.App {

  val f: A => B = (a: A) => new B {}

  def someMethod[Something: C](s: Something) = {
    // uses "s", for example:
    println(s)
  }

  someMethod(f) // Test$$$Lambda$6/1744347043@dfd3711

}

你还没有具体说明让 A -> B 扩展 C 的动机,但显然你希望能够将 A、B 和 A -> B 放在“同一把伞”下,因为你有,比如说,某种方法(称为 someMethod),它采用 C,因此通过继承,您可以向其传递 A、B 或 A -> B 类型的值。

使用类型类,您可以实现相同的目标,并具有一些额外的优点,例如有一天,在不更改现有代码的情况下将 D 添加到系列中(您只需要在范围内的某个位置实现类型 C[D] 的隐式值)。

因此,不是让 someMethod 获取 C 的实例,而是简单地获取某种类型的东西(让我们称之为 s)(让我们称之为它 Something),约束条件是 C[Something] 必须存在。如果您传递 C 实例不存在的内容,您将收到错误:

trait NotC
someMethod(new NotC {}) 
// Error: could not find implicit value for evidence parameter of type C[NotC]

您实现了同样的目标 - 您有一个 C 家族,其成员为 ABA => B ,但是你可以解决子类型问题。

关于scala - 如何在 Scala 中扩展函数类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48263968/

相关文章:

scala - 在 Shapeless 中,我可以为非 case 类提供 `LabelledGeneric` 的实例,以启用类型类实例的自动派生吗?

无法使用信号量的指针访问信号量(我认为我使用的是错误的)

javascript - 有人可以解释一下这个传递的函数是如何返回和调用的吗? - JavaScript

java - 从派生类创建基类对象

java - 子类父类(super class)需要多个构造函数

scala - 在 casbah 的 find() 查询中使用 $in

generics - 方法调用的默认类型

scala - 为什么 play-json 在读取/解析时会丢失精度?

jquery tr 中 td 的每个函数

c# - 简单协方差似乎不适用于 c# 泛型