了解 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 中使用 varargs 柯里化一个函数吗?

    我正在考虑如何用可变参数柯里化一种方法 然后我意识到我什至不知道如何去做 理想情况下 它应该让您可以随时开始使用它 然后以可迭代结束 def concat strs String strs mkString val curriedConca
  • 使用什么框架来引导我的第一个生产 scala 项目?

    我正在第一次涉足 scala 的生产应用程序 该应用程序当前打包为 war 文件 我的计划是创建 scala 编译工件的 jar 文件 并将其添加到 war 文件的 lib 文件夹中 我的增强功能是通过 Jersey 公开的 mysql 支
  • 为什么同样的算法在 Scala 中运行比在 C# 中慢得多?以及如何让它更快?

    该算法根据序列中每个成员的变体创建序列的所有可能变体 C 代码 static void Main string args var arg new List
  • 在泛型方法中返回原始集合类型

    假设我们想要创建一个像这样的函数minBy返回集合中同等极简主义的所有元素 def multiMinBy A B Ordering xs Traversable A f A gt B val minVal f xs minBy f xs f
  • Spark:导入UTF-8编码的文本文件

    我正在尝试处理一个包含很多特殊字符的文件 例如德语变音符号 o 等 如下所示 sc hadoopConfiguration set textinputformat record delimiter r n r n sc textFile f
  • Slick:将操作与 DBIOAction 的 Seq 组合起来

    我有 工作 以下代码 val actions for lt slickUsers insertOrUpdate dbUser loginInfo lt loginInfoAction lt slickUserLoginInfos DBUse
  • 你为什么决定“反对”使用 Erlang?

    Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案或互动 你是否真的 尝试过 意味着在其中编程 而不仅仅是阅读有关它的文章 Erlang并决定在项目中不
  • 函数式 Scala 中的选择排序

    我正在学习 Scala 编程 并编写了选择排序算法的快速实现 然而 由于我对函数式编程还不太了解 所以在转换为更 Scala 风格时遇到了困难 对于 Scala 程序员来说 如何使用 Lists 和 vals 来做到这一点 而不是回到我的命
  • 构造微积分中的“Refl”东西?

    在语言中 例如Agda Idris or Haskell对于类型扩展 有一个 键入类似于以下内容的内容 data a b where Refl a a a b意思是a and b是相同的 这样的类型可以定义在结构演算 https en wi
  • Scala 中的条件未来

    给定这两个 future 仅当条件为真时我才需要运行第一个 future 请参阅if y gt 2 但我有一个例外Future filter predicate is not satisfied 这是什么意思以及如何修复该示例 object
  • 使用 RxJava 限制吞吐量

    我现在遇到的情况很难解释 所以我会写一个更简单的版本来解释这个问题 我有一个Observable from 它发出一系列由ArrayList文件数量 所有这些文件都应上传到服务器 为此 我有一个函数可以完成这项工作并返回一个Observab
  • 如何使用 zio-test 测试异常情况

    我有以下功能 我想测试 def people id Int RIO R People 如果有 People 则此函数返回 Peopleid 分别 如果没有则失败 例如 IO fail ServiceException s No People
  • Scala 工作表在 Intellij 中不起作用

    我有 Intellij IDEA 13 1 2 已编辑 之前为 13 0 2 我使用 scala 插件 我正在尝试使用工作表来评估代码 但我得到的只是两个错误 bad macro impl binding versionFormat is
  • Spark 对 RDD 中按值排序

    我有一个火花对 RDD 键 计数 如下 Array String Int Array a 1 b 2 c 1 d 3 使用spark scala API如何获取按值排序的新RDD对 所需结果 Array d 3 b 2 a 1 c 1 这应
  • 使用 Apache Commons lineIterator 时出现 OutOfMemory 错误

    我正在尝试使用 Apache Commons 逐行迭代 1 2GB 文件FileUtils lineIterator 然而 一旦LineIterator calls hasNext 我得到一个java lang OutOfMemoryErr
  • Scala:为什么 Actor 是轻量级的?

    是什么让演员如此轻盈 我什至不确定它们是如何工作的 它们不是单独的线程吗 当他们说轻量级时 他们的意思是每个参与者都没有映射到单个线程 JVM 提供共享内存线程 锁作为主要形式 并发抽象 但分享了 内存线程是相当重量级的 并招致严重的绩效处
  • 如何插入UUID的值?

    我在 Play Framework 2 3 支持的 postgresql 9 4 中使用 anorm 2 4 给出一个这样的模型 case class EmailQueue id UUID send from String send to
  • 如何编写 sbt 插件来通过代理启动应用程序

    我想在开源之前为我的项目创建一个 sbt 插件 该项目在应用程序运行开始时附加一个 Java 代理 以对其进行各种类型的分析 代理写出文本文件以供以后处理 我希望能够编写一个 sbt 插件 有一个替代方案run called runWith
  • 在 Java 中使用 Scala 常量

    我目前正在评估 Scala 的未来项目 并发现了一些奇怪的事情 我在 JSP 中为我们创建了以下常量 val FORMATED TIME formatedTime 但这没有用 经过一番尝试后 我决定反编译以了解其真相 private fin
  • 自动将通配符导入重构为 IntelliJ 中的显式导入(适用于 Scala/Java)

    考虑下面的代码 是否可以让 IntelliJ 自动将每个通配符导入重构为显式导入 无论范围内使用什么 例如import scalatags JsDom all into import scalatags JsDom all ol li di

随机推荐

  • 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