了解 Scala 中的柯里化

2023-12-11

我在理解柯里化概念或至少是 SCALA 柯里化符号时遇到了问题。

维基百科说柯里化是一种将带有多个参数的函数的求值转换为求值一系列函数的技术,每个函数都有一个参数。

按照这个解释,接下来的两行对于 scala 来说是一样的吗?

def addCurr(a: String)(b: String): String = {a + " " + b}
def add(a:String): String => String = {b => a + " " + b}

我用相同的字符串 a 和 b 运行了两条线,得到了相同的结果,但我不知道它们在幕后是否不同

我对 addCurr (以及柯里化本身)的思考方式是,它是一个接收字符串参数 a 的函数,并返回另一个也接收字符串参数 b 并返回字符串 a + " " + b 的函数?

那么,如果我没猜错的话,addCurr 只是函数 add 的语法糖,并且都是柯里化函数?

根据前面的例子,下一个函数对于scala来说也是等价的吗?

def add(a: String)(b: String)(c: String):String = { a + " " + b + " " + c}

def add1(a: String)(b: String): String => String = {c => a + " " + b + " " + c}

def add2(a:String): (String => (String => String)) = {b => (c => a + " " + b + " " + c)}

它们的语义有些不同,但它们的用例大部分是相同的,无论是在实践中还是在代码中的外观。

Currying

从数学意义上柯里化 Scala 中的函数非常简单:

val function = (x: Int, y: Int, z: Int) => 0
// function: (Int, Int, Int) => Int = <function3>
function.curried
// res0: Int => (Int => (Int => Int)) = <function1>

功能与方法

您似乎对 Scala 中的事实感到困惑,(=>) 功能不等于 (def) methods。方法不是一流的对象,而函数是(即它有curried and tupled方法,以及Function1有更多的好处)。

然而,可以通过称为 eta 扩展的操作将方法提升为函数。看这个答案了解一些细节。您可以通过编写手动触发它methodName _,或者如果您为需要函数类型的地方提供一个方法,那么它将隐式完成。

def sumAndAdd4(i: Int, j: Int) = i + j + 4
// sumAndAdd4.curried // <- won't compile

val asFunction = sumAndAdd4 _ // trigger eta expansion
// asFunction: (Int, Int) => Int = <function2>
val asFunction2: (Int, Int) => Int = sumAndAdd4
// asFunction2: (Int, Int) => Int = <function2>
val asFunction3 = sumAndAdd4: (Int, Int) => Int
// asFunction3: (Int, Int) => Int = <function2>


asFunction.curried
// res0: Int => (Int => Int) = <function1>
asFunction2.curried
// res1: Int => (Int => Int) = <function1>
asFunction3.curried
// res2: Int => (Int => Int) = <function1>
{sumAndAdd4 _}.tupled // you can do it inline too
// res3: Int => (Int => Int) = <function1>

多参数列表的eta扩展

正如您可能期望的那样,eta 扩展将每个参数列表提升为自己的函数

def singleArgumentList(x: Int, y: Int) = x + y
def twoArgumentLists(x: Int)(y: Int) = x + y

singleArgumentList _ // (Int, Int) => Int
twoArgumentLists _ // Int => (Int => Int) - curried!

val testSubject = List(1, 2, 3)

testSubject.reduce(singleArgumentList) // Int (6)
testSubject.map(twoArgumentLists) // List[Int => Int]

// testSubject.map(singleArgumentList) // does not compile, map needs Int => A
// testSubject.reduce(twoArgumentLists) // does not compile, reduce needs (Int, Int) => Int

但这并不是数学意义上的柯里化:

def hmm(i: Int, j: Int)(s: String, t: String) = s"$i, $j; $s - $t"

{hmm _} // (Int, Int) => (String, String) => String

在这里,我们得到一个有两个参数的函数,返回另一个有两个参数的函数。

仅指定其部分参数并不那么简单

val function = hmm(5, 6) _ // <- still need that underscore!

与函数一样,您可以毫不费力地返回一个函数:

val alreadyFunction = (i: Int, j: Int) => (k: Int) => i + j + k

val f = alreadyFunction(4, 5) // Int => Int

按照你喜欢的方式去做——Scala 对很多事情都相当不持任何意见。就我个人而言,我更喜欢多个参数列表,因为我通常需要部分应用一个函数,然后将其传递到某个地方,其中剩余的参数将被给出,所以我不需要显式地进行 eta 扩展,并且我在方法定义站点上享受到简洁的语法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

了解 Scala 中的柯里化 的相关文章

  • 简单的 Scala actor 问题

    我确信这是一个非常简单的问题 但很不好意思地说我无法理解它 我有一个 Scala 值列表 我想使用演员来并行地对每个值进行一些 外部 调用 我想等到所有值都已处理完毕 然后继续 没有共享值被修改 有人可以建议吗 Thanks Scala 中
  • 将列表拆分为多个具有固定元素数量的列表

    如何将元素列表拆分为最多包含 N 个项目的列表 例如 给定一个包含 7 个元素的列表 创建 4 个组 最后一组可能包含较少的元素 split List 1 2 3 4 5 6 seven 4 gt List List 1 2 3 4 Lis
  • 何时使用接口,何时使用高阶函数?

    给定一个具有以下层的 ASP NET MVC 应用程序 UI 视图 CSS Javascript 等 控制器 服务 包含业务逻辑和数据访问 没有单独的数据访问层的原因是我正在使用 SQL 类型提供程序 以下代码可能不起作用 因为它只是原始草
  • Liftweb 环境中的后台任务

    我必须编写守护进程 并且我想使用模型来连接到数据库和一些有用的 Lift 类 是否可以运行 Rails 的 rake 任务的模拟 Scala 社区组上也有类似的问题 答案是使用Actors来做后台处理
  • Scala:在运行时获取 mixin 接口

    我需要在运行时从给定的类获取所有接口 全部加载在类加载器中 例如 如果一个类是这样声明的 trait B trait C trait D class A extends B with C with D 我想在运行时获取这些信息 A 取决于
  • Scala 集合不一致

    为什么 Scala Collections API 中的集合和列表之间缺乏一致性 例如 有不可变的 Set 但也有可变的 Set 如果我想使用后者 我可以简单地这样做 val set Set A set new A 但是 本身不存在可变列表
  • 逆变方法参数类型

    wiki 逆变方法参数类型 https en wikipedia org wiki Covariance and contravariance 28computer science 29 Contravariant method argum
  • 存在函数依赖关系时类型推断如何工作

    考虑下面的代码 LANGUAGE MultiParamTypeClasses FlexibleInstances FunctionalDependencies UndecidableInstances FlexibleContexts cl
  • Scala Array.apply 有何魔力

    来自 scala 2 10 4 的 array scala Array定义为 final class Array T length Int extends java io Serializable with java lang Clonea
  • 最小重复子串

    我正在看 Perl代码高尔夫页面 http www perlmonks org node id 82878 不要问为什么 并遇到了这个 第 3 洞 最小重复图案 编写一个子例程 它接受一个字符串 该字符串可能包含 重复模式 并返回最小的重复
  • 有没有办法捕获 Spark 中使用通配符读取的多个 parquet 文件的输入文件名?

    我使用 Spark 将多个 parquet 文件读取到单个 RDD 中 并使用标准通配符路径约定 换句话说 我正在做这样的事情 val myRdd spark read parquet s3 my bucket my folder parq
  • Scala:类似 Option (Some, None) 但具有三种状态:Some、None、Unknown

    我需要返回值 当有人询问值时 告诉他们以下三件事之一 这是值 没有价值 我们没有关于该值的信息 未知 情况 2 与情况 3 略有不同 示例 val radio car radioType 我们知道该值 返回无线电类型 例如 pioneer
  • Scala 如何忽略 Java 的检查异常?

    例如如果调用 JavaThread sleep这会抛出一个已检查的InterruptedException来自 Scala 源文件 然后不需要将调用包含在 Scala 中try catch Scala 如何删除将调用包围在 a 中的规则tr
  • 如何捕获 Oozie Spark 输出

    有没有办法捕获spark的输出然后将其输入到shell上 我们当前正在使用 scala 创建 jar 文件 并希望我们的 Spark 输出成为 shell 输入 我的想法是使用 wf actionData spark XXXX var 我只
  • Java 表达式树 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有相当于 net的 LINQ 下的表达式树JVM 我想实现一些类似 LINQ 的代码结构Scala
  • 为什么解析器组合器“seq”用“bind”和“return”定义?

    我正在读这个article http eprints nottingham ac uk 237 1 monparsing pdf关于解析器组合器并且不理解以下内容 他们说使用seq 见下文 导致解析器将嵌套元组作为结果 操作起来很混乱 se
  • Scala:如何在超类上实现克隆方法,并在子类中使用它?

    我可能会以错误的方式处理这个问题 但我想要一个像这样的对象 class MyDataStructure def myClone val clone new MyDataStructure do stuff to make clone the
  • 运行具有外部依赖项的 Scala 脚本

    我在 Users joe scala lib 下有以下 jar commons codec 1 4 jar httpclient 4 1 1 jar httpcore 4 1 jar commons logging 1 1 1 jar ht
  • 在 Java 8 中使用映射函数时类型转换不起作用

    我正在比较两个列表 List allUserGroups UserBC getAllGroupsForUser userId deptID List
  • Scala 解析器组合器的运算符优先级

    我正在研究需要考虑运算符优先级的解析逻辑 我的需求并不太复杂 首先 我需要乘法和除法比加法和减法具有更高的优先级 例如 1 2 3 应视为 1 2 3 这是一个简单的例子 但你明白了 我需要将更多自定义标记添加到优先级逻辑中 我可以根据此处

随机推荐

  • TCP 客户端-服务器 SIGPIPE

    我正在设计和测试一个基于TCP套接字 互联网域 的客户端服务器程序 目前 我正在本地计算机上对其进行测试 无法理解有关 SIGPIPE 的以下内容 SIGPIPE 的出现相当随机 它可以是确定性的吗 第一个测试涉及来自客户端的单个小 25
  • php - 从一种 json 格式转换为另一种格式

    我正在使用 php 从 mysql 数据库获取数据 并对获取的输出进行 json 编码 json encode data 结果数据的形式为 name aaa name bbb 我想将其放入一个更大的 json 对象中 并在网络浏览器中以以下
  • Rails EXECJS 运行时错误

    您好 我在 Demo index 中收到 ExecJS RuntimeError 下面是突出显示的第 6 行 下面是我的完整跟踪 有人可以回答 指出我调试此问题的正确方向以及调试轨道的良好参考 我是 Rails 新手 我的猜测是我错过了一个
  • Canny Edge 检测器阈值给出不同的结果

    我正在尝试找到图像的轮廓 在此之前我正在应用 Canny 的边缘检测器 它为不同的图像提供不同的结果 对于一张图像 它在阈值 min 40 max 240 处提供完美的轮廓 而对于其他图像 其阈值为 30 120 我想让它变得通用 通俗地说
  • fgets 不等待键盘输入

    我想从用户的键盘输入中读取两个字符串 这是我尝试过的代码 char nomFichier 50 emp 100 empEtNomFichier 150 printf nDonner le nom du fichier fgets nomFi
  • 从嵌套类设计嵌套反应形式

    我有以下课程 class License name string lots of other fields nameAttributes NameAttributes class nameAttributes NameAttributes
  • 请求响应的顺序与请求的顺序相同吗?

    我正在使用 grequests 使用相同的 url 但不同的参数从网站异步下载数据 例如 unsent requests for param in params assume params is a list containing diff
  • Linux 上的可执行格式列表 [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 在哪里可以找到 Linux 系统上批准 支持的可执行格式的列表 我期待找到一个包含以下内容的列表ELF Shebang a outETC 我已经知道我可以找到 proc sys fs
  • Flex 中的自动化测试

    我想自动化测试 Flex 应用程序 我听说 Flex 提供了可以帮助您自动化测试的类 但我不知道在哪里可以找到它们以及如何使用它们 有人可以帮助我解决这个问题吗 任何提示或建议将不胜感激 是的 这就是所谓的功能测试 Adobe 为 UI 组
  • Prism 7 DI 中的 Register、RegisterInstance 与 RegisterSingleton

    我正在尝试在 Prism 7 中注册 DI 服务 我发现以下所有方法都有效 哪一个是正确的方法 各自的情况如何 public class AndroidInitializer IPlatformInitializer static Open
  • 使用 JavaScript 防止表单提交重定向/刷新

    我有一个页面 您可以在一系列文本框 从 php 生成 中输入数据 以及 2 个按钮 GetData 和 SaveData 我希望能够在编辑文本框时按 Enter 键 并且它将执行与单击 SaveData 按钮 onclick onSave
  • 如何将 Google 云端硬盘文件选择器与 Apps 脚本 HTML 服务结合使用

    有谁有使用示例Google 云端硬盘文件选择器与应用程序脚本HTML服务 有可能吗 我想用它来选择文件或使用 AppsScript HTML 服务从云端硬盘上传文件 不幸的是 由于 Caja 的限制 不可能在 HtmlService 中使用
  • 通过 AJAX 和 jQuery 从 PHP 数组获取数据

    我有一个页面如下
  • Android 设备年龄

    是否可以查询android设备的年龄 我想知道用户拥有他的设备多久 电池的寿命可能是一个很好的指标 但我找不到合适的 API 最佳的是第一次设备启动的时间戳 有任何想法吗 没有可靠的方法来找出设备的年龄 但我们可以通过某种方式找出设备的年龄
  • Android - 从远程服务器加载多个图像的有效方法

    我有一个 Android 应用程序 可以从 php 远程服务器检索数据 图像 文本 并将其显示在 GridView 中 我正在使用 Loaders 在后台进行操作 我对图像和文本有单独的连接 因为检索图像需要更长的时间 而且我想立即显示文本
  • 在 ASP.Net MVC 5 应用程序中使用多个 ASP Identity 2.0

    我有一个带有管理区域的 Web 应用程序 用于管理内容 但该网站的其余部分目前由 ASP Identity 保护 该身份验证我的公共用户 现在我需要对一些内部用户进行身份验证才能访问管理区域 这可能吗 您正在寻找的称为 SSO 单点登录 通
  • 在命令行上使用 Android lint 忽略库项目

    我将 Android lint 与 Jenkins 结合使用 需要忽略我的团队未修改的库项目 特别是 Action Bar Sherlock 以便我们可以从 Android lint 获得有用的结果 目前 我正在从命令行启动 lint 并将
  • 如何从 Google Container Engine 访问 HTTP 请求的客户端 IP?

    我正在使用 Google Container Engine 在 docker 容器中运行 Gunicorn flask 服务 我按照教程设置了集群http kubernetes io docs hellonode The REMOTE AD
  • HttpSessionListener.sessionCreated() 未被调用

    我有一个非常简单的 Servlet 和一个非常简单的 HttpSessionListener WebServlet HelloWorld public class HelloWorld extends HttpServlet private
  • 了解 Scala 中的柯里化

    我在理解柯里化概念或至少是 SCALA 柯里化符号时遇到了问题 维基百科说柯里化是一种将带有多个参数的函数的求值转换为求值一系列函数的技术 每个函数都有一个参数 按照这个解释 接下来的两行对于 scala 来说是一样的吗 def addCu