【问题标题】:Scala Curried Type MismatchScala Curried 类型不匹配
【发布时间】:2019-04-15 05:32:15
【问题描述】:

因此,经过反复试验和对我们教科书的研究,我得到了以下功能,我可以想出一个解决方案。

def prodC1(f : Int => Int) : (Int, Int) => Int = {
  def prodA1(a : Int, b : Int) : Int =
    if(a > b) 1 else f(a) * prodA1(a+1, b)
  prodA1 // Why do i need this line here 
}

如果我没有说明我的类型不匹配,有人可以详细说明/解释这条线的要求吗?

【问题讨论】:

    标签: scala currying


    【解决方案1】:

    所以你需要知道很多事情才能真正理解这个问题的答案。

    在 Scala 中,任何def 都是method,它只不过是一些object 的成员之一。 methods 不是 Scala 中的一等成员,这也意味着 methods 不能单独存在。

    在 Scala 中,任何事物的 value 都必须是 expression。这意味着def 的 RHS 必须是类似def abc = some-expression 的表达式。表达式示例有11 + 1"xyz"anotherMethodCallWhichWillReturnAnExpression() 等。

    def abc = xxxxxx 这样的东西在Scala 语言定义中不是expression。因此你不能这样做,

    def prodC1(f : Int => Int) : (Int, Int) => Int = {
      def prodA1(a : Int, b : Int) : Int =
        if(a > b) 1 else f(a) * prodA1(a+1, b)
    }
    

    现在,当您添加带有prodA1 的额外行时,您是在告诉Scala 返回您刚刚定义的prodA1。但请记住,prodA1 只是一个 method,因此不能单独存在,因此实际上无法返回。

    functions 是 Scala 中的第一类成员(表示为各种 FunctionX 类之一的实例),因此可以返回。

    在这种情况下,Scala 会智能地将这个method 提升为function 类型为(Int, Int) => Int。这称为 eta 扩展。

    更详细地了解事物。您可以打开 Scala 控制台并尝试以下操作。

    scala> val s = "abc"
    // s: String = abc
    
    scala> val i = 10
    // i: Int = 10
    
    
    scala> def prodA1(a : Int, b : Int) : Int = if (a > b) 1 else a * prodA1(a+1, b)
    // prodA1: (a: Int, b: Int)Int
    

    注意实际valuesdef 的Scala 控制台输出之间的差异。现在,如果我尝试将prodA1 用作valueval,我将收到以下错误。

    scala> val x = prodA1
    // <console>:12: error: missing argument list for method prodA1
    // Unapplied methods are only converted to functions when a function type is expected.
    // You can make this conversion explicit by writing `prodA1 _` or `prodA1(_,_)` instead of `prodA1`.
    //        val x = prodA1
    

    Scala 告诉您,您可以使用_method 显式转换为function。让我们试试吧。

    scala> val x = prodA1 _
    // x: (Int, Int) => Int = $$Lambda$1077/293669143@13278a41
    

    现在xfunction 类型的(Int, Int) =&gt; Int

    另外,第一行 Unapplied methods are only converted to functions when a function type is expected. 告诉您您的案例中实际发生的情况。

    由于预计prodC1 会返回(Int, Int) =&gt; Int 类型的function,并且您提供了prodA1,因此Scala 使用eta-expansion 自动将您的method 转换为function

    【讨论】:

    • 非常感谢您将“prodA1”替换为“return prodA1(,)”的解释在语法上对我来说更有意义。
    • 这实际上是一个很大的思维转变。像return 1def abc = { return 1 } 这样的东西更像是statement,而def abc = 1 中的1expression。你越倾向于函数式编程,你就会开始发现表达式比语句更符合逻辑。
    • 尽管我喜欢你的鼓励,但我并不是函数式编程的忠实粉丝,但时间会证明一切。 :->
    【解决方案2】:

    让我们看看你的返回类型。

    def prodC1(f : Int => Int) : (Int, Int) => Int = {
      def prodA1(a : Int, b : Int) : Int =
        if(a > b) 1 else f(a) * prodA1(a+1, b)
      prodA1 // Why do i need this line here 
    }
    

    你的返回类型是

     (Int, Int) => Int 
    

    这是Function2[Int, Int, Int]的scala糖

    第一个参数是第一个参数的类型,第二个参数是第二个参数的类型,最后一个是返回参数的类型

    返回实例需要是一个函数

    prodA1 符合该类型,表示允许返回。

    【讨论】:

      【解决方案3】:

      您的函数需要返回 (Int, Int) => Int 的实例。

        def prodA1(a : Int, b : Int) : Int =
          if(a > b) 1 else f(a) * prodA1(a+1, b)
      

      创建一个名为 prodA1 的 (Int, Int) =&gt; Int 类型的函数,但定义内部函数的返回类型不会创建任何实例,因此该函数的返回类型是 Unit

      因此您需要返回具有正确类型的prodA1..

      【讨论】:

        猜你喜欢
        • 2012-08-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-25
        • 2015-04-09
        • 1970-01-01
        相关资源
        最近更新 更多