scala - Scala Curried 类型不匹配
问题描述
因此,在我们的教科书中经过反复试验和研究后,我得到了以下功能,我可以想出一个解决方案。
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 中 anydef
是 a method
,它只不过是 some 的成员之一object
。methods
不是 Scala 中的一等成员,这也意味着它们methods
不能单独存在。
在 Scala 中,value
任何事物的 of 都必须是expression
. 这意味着 a 的 RHSdef
需要是一个类似的表达式def abc = some-expression
。表达式的示例是1
, 1 + 1
,"xyz"
等anotherMethodCallWhichWillReturnAnExpression()
。
类似的东西def abc = xxxxxx
不是expression
Scala 语言中的定义。因此你不能这样做,
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
您刚刚定义的 this。但是记住prodA1
只是一个method
,因此不能单独存在,因此实际上不能返回。
但是functions
是 Scala 中的第一类成员(表示为各种类之一的实例FunctionX
),因此可以返回。
在这种情况下,Scala 将智能地将其提升method
为 a function
of type (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
注意 Scala 控制台的实际输出values
和def
. 现在,如果我尝试使用prodA1
as value
,val
我会收到以下错误。
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
现在x
是一个function
类型(Int, Int) => Int
。
此外,第一行Unapplied methods are only converted to functions when a function type is expected.
告诉您您的案件实际发生了什么。
由于prodC1
预计会返回 afunction
类型(Int, Int) => Int
并且您提供了prodA1
,因此 Scala 曾经eta-expansion
自动将您转换method
为function
.
推荐阅读
- java - 为什么 OnClick 方法没有执行?
- c++ - 是否可以在 c++ 的输出中显示小数?
- elasticsearch - Elasticsearch6.8如何第二次缓存同一个请求?
- symfony - 如何在 Symfony Cloud Project 中删除快照?
- sctp - “sctp assocs”显示中的“*A”和“*U”是什么意思?
- c# - 我的程序中的 ArgumentOutOfRangeException
- vcpkg - 更改 vcpkg 库的目标名称(dll 名称)的最简单方法
- css - 在 Firefox 中的两行文本末尾对齐 ::after 元素
- eslint - 如何忽略电子反应样板项目中的 eslint 规则?
- php - 非静态方法 App\Http\Models\Role::id_role() 不应在 laravel 中静态调用