scala - 是否可以将翻转实现为 Scala 函数(而不是方法)

标签 scala

作为学习 Scala 的一部分,我尝试在 Scala 中实现 Haskell 的翻转函数(具有签名 (A => B => C) => (B => A => C) 的函数) - 并将其实现为函数(使用val) 而不是作为方法(使用 def)。

我可以将它实现为一种方法,例如这样:

def flip[A, B, C](f: (A, B) => C):((B, A) => C) = (b: B, a: A) => f(a, b)
val minus = (a: Int, b: Int) => a - b
val f = flip(minus)
println(f(3, 5))

但是,当我尝试将其实现为函数时,它不起作用:
val flip = (f: ((Any, Any) => Any)) => ((a: Any, b: Any) => f(b, a))
val minus = (a: Int, b: Int) => a - b
val f = flip(minus)
println(f(3, 5))

当我尝试编译此代码时,它会失败并显示以下消息:
Error:(8, 18) type mismatch;
found   : (Int, Int) => Int
required: (Any, Any) => Any
val f = flip(minus)

我理解它为什么会失败:我尝试通过 (Int, Int) => Int where (Any, Any) => Any 是预期的。但是,我不知道如何解决这个问题。有可能吗?

最佳答案

与方法不同,Scala 不支持多态函数。这是由于函数的第一类值性质,它们只是 FunctioN 的实例。特征。这些函数是类,它们需要在声明处绑定(bind)类型。

如果我们采取flip方法并尝试将其扩展为一个函数,我们会看到:

val flipFn = flip _

我们将返回一个类型的值:
((Nothing, Nothing) => Nothing) => (Nothing, Nothing) => Nothing

由于没有绑定(bind)任何类型,因此编译器使用了按钮类型 Nothing .

然而,并不是所有的希望都落空了。有一个名为 shapeless 的库这确实允许我们通过 PolyN 定义多态函数.

我们可以这样实现翻转:
import shapeless.Poly1

object flip extends Poly1 {
  implicit def genericCase[A, B, C] = at[(A, B) => C](f => (b: B, a: A) => f(a, b))
}
flipFunctionN 没有什么不同trait,它定义了一个 apply将被调用的方法。

我们像这样使用它:
def main(args: Array[String]): Unit = {
  val minus = (a: Int, b: Int) => a - b
  val f = flip(minus)
  println(f(3, 5))
}

产量:
2

这也适用于 String :
def main(args: Array[String]): Unit = {
  val stringConcat = (a: String, b: String) => a + b
  val f = flip(stringConcat)
  println(f("hello", "world"))
}

产量:
worldhello

关于scala - 是否可以将翻转实现为 Scala 函数(而不是方法),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46160357/

相关文章:

scala - 如何运行不阻塞主线程但在主线程失败时抛出异常的异步 IO 操作?

scala - Spark 使用递归案例类

arrays - 什么时候应该使用Scala的Array而不是其他集合之一?

java - 试图在 Java 中初始化 Scala 创建的类

scala - 如果类型是 HList 的成员,我如何检查无形?

database - 哪些 ORM 与 Scala 配合得很好?

java - 如何在 scala 中使用函数式编程过滤列表?

java - scala模板 Play Framework 中的if语句

scala - Spark joinWithCassandraTable() 映射多个分区键错误

scala - sbt 子项目的项目目录