【问题标题】:scala generic function referencescala 泛型函数参考
【发布时间】:2022-01-25 16:07:16
【问题描述】:

我有几个具有相同签名的通用函数:

def f1[A, B](v: A, f: (A, B) => B): B = ...

def f2[A, B](v: A, f: (A, B) => B): B = ...

而且我需要定义一个函数g,它可以接受任何这些函数(f1f2):

def g(f: ????) = ...

g 内部使用了多种参数类型,所以我不能这样参数化它:

def g[A, B](f: (A, (A, B) => B) => B) = ...

【问题讨论】:

  • 具有多种参数类型的 WDYM?为什么简单的类型参数不起作用?

标签: scala functional-programming


【解决方案1】:

在 Scala 2 中确实没有比这更好的方法了。尽管您的解决方案有点奇怪,因为 FunctionHolderapply 方法将返回一个函数对象并且本身不接受任何参数 –这比它需要的要复杂一些。所以你可以这样做:

trait FunctionHolder {
  def apply[A, B](v: A, f: (A, B) => B): B
}

def g(f: FunctionHolder) = …

但这并没有那么好。

在 Scala 3 中,polymorphic function types 可以更简洁地执行此操作:

def g(f: [A, B] => (A, (A, B) => B) => B) = …

也就是说,我不相信那个类型签名真的是你想要的。请记住,当您使用类型参数定义函数时,它需要为用户可能提供的所有 可能的类型参数工作。此签名无法执行此操作...

def f1[A, B](v: A, f: (A, B) => B): B

...因为当我有这样的函数时,我可以轻松编写Nothing 类型的表达式:

f1[Unit, Nothing]((), (a: Unit, b: Nothing) => b)

并且不可能编写Nothing 类型的表达式,除非你作弊(例如,抛出异常或进入无限循环或类似的东西)。所以类型签名告诉我你在作弊?

如果您想了解更多关于这种推理的信息,请搜索“免费定理!”

【讨论】:

    【解决方案2】:

    闲逛了一下,得出以下结论:

    g(new FunctionHolder {
        def apply[A, B](): (A, (A, B) => B) => B = f1
    })
    
    
    def g(f: FunctionHolder) = f()(..., (a, b) => ...)
    
    abstract class FunctionHolder {
        def apply[A, B](): (A, (A, B) => B) => B
    }
    

    但这看起来不对。

    希望有更简洁的方法来做到这一点

    【讨论】:

      猜你喜欢
      • 2021-02-21
      • 2021-08-19
      • 1970-01-01
      • 2012-03-05
      • 1970-01-01
      • 1970-01-01
      • 2017-06-20
      • 1970-01-01
      • 2018-01-01
      相关资源
      最近更新 更多