OCaml 会将多参数函数转换为柯里化函数还是反之亦然?

2023-11-30

当我学习 OCaml 基础知识时,我被告知 OCaml 中的每个函数实际上都是一个只有一个参数的函数。多参数函数实际上是一个接受一个参数并返回一个函数,该函数接受下一个参数并返回......

这是柯里化,我明白了。

所以我的问题是:

case 1

if I do

let plus x y = x + y

在 OCaml 编译时,OCaml 会将其更改为let plus = fun x -> fun y -> x + y?


或者反过来

case 2

If I do

let plus = fun x -> fun y -> x + y

OCaml 会将其转换为let plus x y = x + y?


哪个案例是真实的? OCaml 编译器在正确的情况下做了什么好处或优化?

另外,如果case 2是的,那么考虑 OCaml 进行柯里化有什么意义呢?我的意思是它实际上是相反的,对吧?

这个问题实际上与理解Core的`Fn.const`


Both let plus x y = x + y and let plus = fun x -> fun y -> x + y将被编译为相同的代码:

camlPlus__plus:
    leaq    -1(%rax, %rbx), %rax
    ret

是的,正是两条汇编指令,没有任何序言和尾声。

OCaml 编译器执行几个优化步骤,实际上是在不同的类别中“思考”。例如,两个函数都用相同的 lambda 代码表示:

(function x y (+ x y))

我认为,根据上面的 lambda,您可能会认为 OCaml 编译器会转换为非柯里化版本。

Update

我还想补充几句关于核心的内容const功能。假设我们有 const 函数的两个语义等价表示:

let const_xxx c = (); fun _ -> c
let const_yyy c _ = c

在 lambda 形式中,它们将表示为:

(function c (seq 0a (function param c))) ; const_xxx
(function c param c)                     ; const_yyy

所以,正如你所看到的,const_xxx确实是以柯里化形式编译的。

但最有趣的问题是,为什么值得用如此晦涩的代码来编写它。也许汇编输出(amd64)中有一些线索:

camlPlus__const_xxx_1008:
    subq    $8, %rsp
.L101:
    movq    %rax, %rbx                    ; save c into %rbx (it was in %rax)
.L102:  
    subq    $32, %r15                     ; allocate memory for a closure
    movq    caml_young_limit(%rip), %rax  ; check
    cmpq    (%rax), %r15                  ; that we have memory, if not
    jb      .L103                         ; then free heap and go back
    leaq    8(%r15), %rax                 ; load closure address to %rax
    movq    $3319, -8(%rax)
    movq    camlPlus__fun_1027(%rip), %rdi
    movq    %rdi, (%rax)
    movq    $3, 8(%rax)
    movq    %rbx, 16(%rax)                ; store parameter c in the closure
    addq    $8, %rsp             
    ret                                   ; return the closure
.L103:  call    caml_call_gc@PLT
.L104:  jmp .L102

关于什么const_yyy?它被简单地编译为:

camlPlus__const_yyy_1010:
    ret

只需返回参数即可。因此,假设实际的优化点是const_xxx闭包的创建是在函数内部编译的,并且应该很快。另一方面,const_yyy不希望以柯里化方式调用,因此如果您在没有所有所需参数的情况下调用它,那么编译器需要添加在以下位置创建闭包的代码const_yyy部分应用(即执行const_xxx每次你打电话const_xxx x).

总而言之,const优化创建一个针对部分应用程序进行优化的函数。虽然,这是有代价的。未优化的const如果使用所有参数调用函数,其性能将优于优化后的函数。 (实际上我的参数甚至放弃了对const_yyy当我用两个参数应用它时。

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

OCaml 会将多参数函数转换为柯里化函数还是反之亦然? 的相关文章

  • OCaml 中的“[< >]”是什么意思?

    我看过一些源代码 let rec parse document parser lt len parse int32 st gt gt parse list ES take int32 len st lt gt gt malformed pa
  • Ocaml 多态记录类型不太通用

    给定以下类型 type props state reactInstance props props state state updater event props state reactInstance gt event gt state
  • 程序程序员的功能代码片段列表? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 修复 OCaml 中的数据类型

    Haskell 中的以下数据类型如何用 OCaml 或 SML 表示 newtype Fix f In f Fix f 我已经在邮件列表上回答了这个问题 https sympa inria fr sympa arc caml list 20
  • 什么是主要类型?

    OCaml 编译器有一个 principal 选项 邮件列表中有时会提到术语 principal type 它到底是什么意思 维基百科中的定义是递归的 因为它假设读者已经熟悉这个概念 类型推断的过程就是猜测给定用户编写的程序 该程序的类型是
  • 如何在 JavaScript 中表示代数数据类型和模式匹配

    在像 OCaml 这样的函数式语言中 我们有模式匹配 例如 我想记录用户在我的网站上的操作 操作可以是 1 访问网页 2 删除项目 3 检查其他用户的个人资料等 在 OCaml 中 我们可以编写如下内容 type Action VisitP
  • 在 OCaml 中将哈希表转换为对(键,值)列表

    OCaml 中有没有办法将哈希表转换为 键 对 值列表 我知道 给定一个哈希表ht我们可以做的 BatList of enum BatHashtbl enum ht 使用电池库 这会将表转换为枚举 然后将枚举转换为列表 但我正在寻找一种不使
  • 使用第一类模块时,类型构造函数“...”将转义其范围

    给定一个简单的工厂 module type Factory sig type t val create unit gt t end module FactoryImpl Factory struct type t string let cr
  • 扁平列表和免费 monad

    我试图说服自己 List monad 具有平面列表 列表串联和按元素映射的列表 不是一个自由 monad 准确地说 是与某个函子 T 关联的自由 monad 据我了解 我应该能够通过以下方式实现这一目标 首先在 monad 列表中找到常用运
  • 在 OCaml 中编写 main 脚本?

    如何在 OCaml 中模拟这个 Python 习惯用法 if name main main See 罗塞塔代码 http rosettacode org wiki ScriptedMain Python其他编程语言的示例 Ocaml 中没有
  • OCaml 是否复制了自定义块?

    想象一下 我有一个名为 libcat 的 C 库 用于与我的毛茸茸的猫进行交互 因此 我正在为 OCaml 编写绑定来简化与 fluffy 的交互 module type CAT sig type cat val find gt cat v
  • android ndk:-fPIC 和 -pie 是互斥的吗?

    我正在使用 Android r10e NDK 为 Android 构建 Unison 文件同步可执行文件 但这并不是真正的 Android 问题 Android gt 5 0 SDK 21 要求可执行文件与位置无关 所以我 编译时将 pie
  • OCaml 在运行时编译和加载

    我正在尝试实现类似的目标eval 在 OCaml 中 我有一个string我想从中得到一个 OCaml 函数 目前我正在做以下事情 我将字符串转储到new ml并编译文件 Compile implementation Format std
  • 什么才是真正性能更高的? Haskell 或 OCaml [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 类型变量和局部抽象类型有什么区别?

    我试图理解的目的局部抽象类型在 OCaml 中 局部抽象类型与类型变量有何不同 看来他们有相同的行为 Type variable let f x a a x val f a gt a
  • 使用 OCaml 警告属性禁用警告 8:不详尽的匹配

    我正在尝试编写类似于以下内容的代码 let a b body 1 2 我想仅针对该模式禁用警告 8 a b 而不是为了身体或让之外的任何东西 我尝试设置警告属性来禁用警告 但以下方法都不起作用 let warning 8 a warning
  • 如何缩进现有 OCaml 代码

    我有大约 30 000 行缩进严重的 OCaml 代码 包括 mly 和 mll 文件 并且想要缩进它们 我尝试在谷歌上搜索 ocaml indent 的变体 我能得到的最接近的结果是使用 Omlet vim 并一次缩进一行代码 在插入模式
  • 在 OCaml 自定义顶层设置提示

    在 OCaml 自定义顶层中 有没有一种方法可以通过编程方式设置提示 到别的东西 我希望能够更改它以响应用户的最后一个自定义功能 有点像bash你如何设置PS1 我什至找不到 directive 来更改它 谢谢 在 toplevel top
  • 链接“let”语句时使用“and”还是“in”更好?

    我意识到这可能是一个愚蠢的问题 但是 如果我把一堆let不需要需要了解彼此价值观的语句 使用是否更好and or in 例如 以下哪一个更可取 如果有 let a foo and b bar and c baz in etc or let
  • OCaml 作为 C 库,hello world 示例

    我希望通过 C 调用 OCaml 代码 方法是将 OCaml 编译为包含 C 接口的静态或共享库 这一页 https caml inria fr pub docs manual ocaml intfc html似乎解释了如何为 OCaml

随机推荐

  • 如何建立自引用表

    在源表中 有两列 如下快照所示 那么对于目标表 它应该是这样的 DimLocationKey 是自动生成的代理键 如何在SSIS中实现自引用效果 我尝试了以下方法 但它不起作用 因为查找中没有匹配项 如果该列可为空 则您可以加载 locat
  • 在char数组中间插入字符

    我有一个填充了一些字符的字符数组 假设我的字符数组中有 HelloWorld 不是字符串 占用索引0到9 我想做的是在数组中间插入一个字符 然后将其余字符推到一边 为要插入的新字符腾出空间 因此 我可以使 char 数组中包含 Hello
  • 理解和实现 R 中分位数函数的数值积分

    我需要使用 R 计算下面的积分 我设法在 R 中使用分位数回归完成 q theta x 函数 包 quantreg matrix structure c 0 01 0 02 0 03 0 04 0 05 0 06 0 07 0 08 0 0
  • cakePHP 文件下载未找到或不可读

    我现在已经挣扎了一个小时试图解决这个问题 我用它来下载文件app uploads 目录 它说目录未找到或不可读 但我检查了它 它也存在使用的文件 file File filename 我想知道我在这里缺少什么 file this gt Fi
  • 在executeBatch()之后使用CallableStatement检索ResultSet

    我需要多次调用存储过程并使用executeBatch 为了这 每次调用都应返回包含结果的表 但我无法访问此结果 接下来的代码工作正常 callableStatement setString 1 foo callableStatement s
  • 重新设计后如何拒绝来自 iTunes Connect 的二进制文件 (12/09/2014)?

    我需要拒绝我的二进制文件 以便重新上传 这一直是 iTunes connect 上的一个隐藏选项 现在重新设计了 我到处找都找不到 根据苹果自己的文档 从审核中删除您的版本 打开应用程序的 应用程序详细信息 页面 如中所述打开应用程序的 应
  • 如果安装了3.5,还需要.net Framework 2.0吗?

    我想知道如果安装了 net Framework 3 5 运行 net 2 0应用程序是否仍然需要 net Framework 2 0 谢谢 Net 3 5 实际上是 Net 2 0 加上一些额外功能 除非 Net 2 0 也存在 否则无法安
  • re.findall 表现得很奇怪

    源字符串是 Python 3 4 3 s r abc123d hello 3 1415926 this is my book 这是我的模式 pattern r 0 9 0 9 0 9 然而 re search可以给我正确的结果 m re s
  • 如何防止用户在 Ionic/Cordova 中截屏?

    是否可以阻止用户在使用 Ionic Cordova 开发的 Android 应用程序中截取屏幕截图 如果可以的话 怎样做 我在 Ionic 论坛上提问 但没有得到答案 是的 您可以使用插件来做到这一点 使用这里的一个 http blog d
  • 是否有使用 @Version 的可配置替代方案?

    我正在放置一个带注释的字段 Version在我所有的 JPA 域类中 但这似乎只是额外的样板 有没有办法通过配置来解决这个问题 TIA Ole 据 JPA 规范告诉我们 您无法更改 Version通过 配置 进行注释 你要么使用 Versi
  • 异步回发后如何保持整个页面滚动位置

    我正在使用 asp net 4 0 iis 7 5 microsoft Visual Studio 2010 我想要的是当异步回发发生时 更新面板 保持整个页面 浏览器 滚动位置 不是 div 或面板 我怎样才能做到这一点 实际上我有一个函
  • 动态添加到 TableLayoutPanel 的行显示在不同的行位置

    我正在尝试通过单击按钮将 TextBox 动态添加到 TableLayoutPanel 中 通过单击鼠标选择行 选择行后 单击按钮将在所选行号上插入文本框 Problem是正确之后显示在不同选定的行上使用 TextBox 3 或 4 次 进
  • 如何更改 ScrollBar 的宽度?

    我想更改 TFrame 的 ScrollingBar 宽度 我知道我可以通过以下方式更改系统中的所有 ScrollingBar SystemParametersInfo SPI SETNONCLIENTMETRICS 但是我该如何为特定的
  • Haskell 列表错误的部分和

    我需要在 Haskell 中编写一个函数 对列表的元素求和 直到某些特定元素存储在另一个列表中 例如partial add 1 2 3 4 5 6 2 5 0应该返回 3 12 6 我已经达到了这样的程度 partial add count
  • 删除数组中连续出现的重复项

    有什么方法可以从下面的数组中删除连续的重复项 同时只保留第一个重复项 该数组如下所示 a array 1 gt go 2 gt stop 3 gt stop 4 gt stop 5 gt stop 6 gt go 7 gt go 8 gt
  • 如何在 Mac OS cocoa 中获取已安装 USB 设备的设备 ID、供应商 ID 和产品 ID

    我正在尝试编写一个 Cocoa 程序来检测连接到 Mac OS 的 iPod 我正在监听 NSWorkspaceDidMountNotification 和 NSWorkspaceDidUnmountNotification 以获取 USB
  • JObject.Parse 与 JsonConvert.DeserializeObject

    JsonConvert DeserializeObject 和 JObject Parse 有什么区别 据我所知 两者都采用字符串并且都在 Json NET 库中 什么样的情况会让一种情况比另一种更方便 或者主要只是偏好 作为参考 下面是我
  • Azure API 管理:带有后端 API 的 Oauth2

    我有一个后端 API 想要使用 Azure API 管理进行代理 该后端 API 要求我提供 Bearer Oauth2 令牌 我想使用 Azure APIM 为我处理 Oauth2 流 并且我想公开一个非常简单的 API 供客户端应用程序
  • 如何在我的多面标签之一中包含希腊符号?

    我正在尝试使用 ggplot2 v 2 2 2 1 创建一个绘图facet wrap 并且我只需要在一个方面标签中包含一个希腊符号 共五个 我尝试使用 Stack Overflow 上发布的代码 R 分面网格中分面标签的 R 希腊字母和普通
  • OCaml 会将多参数函数转换为柯里化函数还是反之亦然?

    当我学习 OCaml 基础知识时 我被告知 OCaml 中的每个函数实际上都是一个只有一个参数的函数 多参数函数实际上是一个接受一个参数并返回一个函数 该函数接受下一个参数并返回 这是柯里化 我明白了 所以我的问题是 case 1 if I