【问题标题】:is it possible to implement flip as a Scala function (and not a method)是否可以将翻转实现为 Scala 函数(而不是方法)
【发布时间】:2018-02-19 23:17:09
【问题描述】:

作为学习 Scala 的一部分,我尝试实现 Haskell 的 flip 函数(带有签名的函数 (A => B => C) => (B => A => C )) 在 Scala 中 - 并将其实现为函数(使用 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 其中 (Any, Any) => Any 是预期的。但是,我不知道如何解决这个问题。有可能吗?

【问题讨论】:

  • def something 可能不是一个函数,但它返回一个函数,这有什么问题?

标签: scala


【解决方案1】:

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

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

val flipFn = flip _

我们会返回一个类型的值:

((Nothing, Nothing) => Nothing) => (Nothing, Nothing) => Nothing

由于没有绑定任何类型,因此编译器使用了按钮类型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 特征没有什么不同,它定义了一个将被调用的 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-28
    • 1970-01-01
    相关资源
    最近更新 更多