【问题标题】:Typed Function and Currying in ScalaScala 中的类型化函数和柯里化
【发布时间】:2015-04-17 23:30:47
【问题描述】:

在 Scala 中,假设我有一个这样的函数:

def foo[R](x: String, y: () => R): R

所以我可以这样做:

val some: Int = foo("bar", { () => 13 })

有没有办法改变它以使用函数柯里化而不“丢失”第二个参数的类型?

def foo[R](x: String)(y: () => R): R
val bar = foo("bar") <-- this is now of type (() => Nothing)
val some: Int = bar(() => 13) <-- doesn't work

【问题讨论】:

    标签: scala


    【解决方案1】:

    函数不能有类型参数,你必须使用这样的自定义类:

    def foo(x: String) = new {
      def apply[R](y: () => R): R = y()
    }
    
    val bar = foo("bar")
    val some: Int = bar(() => 13)
    // Int = 13
    

    为避免结构类型,您可以显式创建自定义类:

    def foo(x: String) = new MyClass...
    

    【讨论】:

    • 我认为第二个建议更好,因为它不使用结构类型(总是带有反射 afaik?)。至少我收到以下功能警告:警告:“应通过使隐式值 scala.language.reflectiveCalls 可见来启用结构类型成员方法的反射访问。这可以通过添加导入子句'import scala.language。 ReflectiveCalls' 或通过设置编译器选项 -language:reflectiveCalls。"
    【解决方案2】:

    senia 答案的变体,以避免结构类型:

    case class foo(x: String) extends AnyVal {
      def apply[R](y: () => R): R = y()
    }
    
    val bar = foo("bar")
    val some: Int = bar(() => 13)
    // Int = 13
    

    【讨论】:

    • 你真的应该接受senia的回答,我所做的只是显示一个小变种!除了荣誉之外,声望超过 20k 并没有什么物质上的好处。
    【解决方案3】:

    并不是真正解决您的问题,只是指出如果您明确提供类型,您仍然可以使用函数的第二个版本:

    scala> def foo[R](x: String)(y: () => R): R = y()
    foo: [R](x: String)(y: () => R)R
    
    scala> val bar = foo[Int]("bar") _
    bar: (() => Int) => Int = <function1>
    
    scala> bar(() => 12)
    res1: Int = 12
    

    【讨论】:

      猜你喜欢
      • 2021-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-30
      • 2011-11-03
      • 1970-01-01
      • 2011-08-06
      相关资源
      最近更新 更多