函数是如何柯里化的?

2024-01-20

我了解柯里化的概念是什么,并且知道如何使用它。这些不是我的问题,而是我很好奇这是如何在比 Haskell 代码更低的级别上实际实现的。

例如,当(+) 2 4被柯里化,是一个指向2维持直到4被传入?甘道夫会扭曲时空吗?这是什么魔法?


简短回答:是的,维护一个指向2直到4被传入。


比必要的答案更长:

从概念上讲,您应该认为 Haskell 是根据 lambda 演算和术语重写来定义的。假设您有以下定义:

f x y = x + y

这个定义对于f在 lambda 演算中,结果如下所示,其中我在 lambda 主体周围明确添加了括号:

\x -> (\y -> (x + y))

如果您不熟悉 lambda 演算,这基本上是说“参数的函数x返回(参数的函数y返回(x + y))"。在 lambda 演算中,当我们将这样的函数应用于某个值时,我们可以通过函数体的副本来替换函数的应用,并用该值替换函数的参数。

那么表达式f 1 2通过以下重写顺序进行评估:

(\x -> (\y -> (x + y))) 1 2
(\y -> (1 + y)) 2                 # substituted 1 for x
(1 + 2)                           # substituted 2 for y
3

所以你可以在这里看到,如果我们只提供一个参数f,我们会停在\y -> (1 + y)。因此,我们得到了一个完整的术语,它只是一个将 1 加到某个东西上的函数,完全与我们原来的术语分开,它可能仍在某处使用(对于其他参考文献f).

关键是,如果我们实现这样的函数,每个函数只有一个参数,但有一些返回函数(以及一些返回函数,它们返回返回...的函数)。每次我们应用一个函数时,我们都会创建一个新术语,将第一个参数“硬编码”到函数体中(包括该函数返回的任何函数体)。这就是柯里化和闭包的方式。

显然,这不是 Haskell 直接实现的方式。曾几何时,Haskell(或者可能是它的前身之一;我不太确定历史)是由图简化 http://en.wikipedia.org/wiki/Graph_reduction。这是一种与我上面描述的术语减少等效的技术,它自动带来惰性评估和相当数量的数据共享。

在图简化中,一切都是对图中节点的引用。我不会讲太多细节,但是当评估引擎将函数的应用减少为值时,它copies与函数体相对应的子图,必要时用参数值替换函数的参数(但共享对不受替换影响的图节点的引用)。所以本质上,是的,部分应用函数会在内存中创建一个新结构,该结构引用所提供的参数(即“指向2),并且您的程序可以传递对该结构的引用(甚至可以共享它并多次应用它),直到提供更多参数并且实际上可以减少它。然而,它并不只是记住函数并累积参数直到获得所有参数;评估引擎实际上在每次应用于新参数时都会执行一些工作。事实上,图缩减引擎甚至无法区分返回函数但仍需要更多参数的应用程序与刚刚获得最后一个参数的应用程序之间的区别。

我无法告诉您更多有关 Haskell 当前实现的信息。我相信它是图简化的遥远突变体后代,具有大量巧妙的捷径和更快的条纹。但我的看法可能是错的;也许他们已经找到了一种完全不同的执行策略,它与图形简化完全不同。但我 90% 确信它最终仍会传递保留对部分参数的引用的数据结构,并且它可能仍然会执行相当于部分分解参数的操作,因为这对于惰性求值似乎非常重要作品。我也相当确定它会做很多优化和捷径,所以如果你直接调用一个有 5 个参数的函数,比如f 1 2 3 4 5它不会经历通过连续更多“硬编码”复制 f 主体 5 次的所有麻烦。

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

函数是如何柯里化的? 的相关文章

  • 通过 Emacs 评估 ghci 或 Hugs 中的缓冲区

    在 Emacs 中使用 sml mode 我已经能够使用以下命令将缓冲区内容直接发送到较差的 SML 进程C c C b 现在我只想用 Haskell 做同样的事情 Haskell 模式似乎不支持这一点 所以我想知道 使用 Emacs 和
  • C 在函数中返回数组

    我对 C 比较陌生 我习惯用 Java 编程 所以我发现 C 在涉及数组的方面有点困难 我仍然对这些案例感到困惑 int a int a int a 在java中 我会做这样的事情来在函数中返回一个数组 int returnArr int
  • 生成所有可能的树

    给定以下数据类型定义 data FormTree Empty Node FormTree FormTree deriving Show 我想编写一个函数 它生成一个无限列表 其中包含按长度排序的所有可能的树 例如节点数量 下面的代码几乎满足
  • 比较两个constexpr指针不是constexpr吗?

    我正在寻找一种在编译时将类型映射到数值的方法 理想情况下不使用中建议的哈希this https stackoverflow com a 36122101 2173029 answer 由于指针可以是constexpr 我尝试过这个 stru
  • Ruby 反向柯里化:这可能吗?

    关于 Ruby 1 9 x 中的柯里化 我一直在某些地方使用它 并且可以像基本上支持 proc 参数的默认参数一样进行翻译 p proc x y z x y z p curry 1 gt returns a lambda p curry 1
  • ErrorT 已弃用,但 exceptT 不适合

    我有一个一元计算 在某些时候 由于单子模式匹配 它开始需要 MonadFail 约束 我的简单解决方法是使用以下命令运行它 fmap either error id runErrorT 然而哎呀 Deprecated Use Control
  • Haskell 中的前提条件检查有哪些选项

    这是一个简单的问题 我认为答案很复杂 一个非常常见的编程问题是函数返回某些内容 或者前置条件检查失败 在Java中 我会使用一些抛出异常的断言函数IllegalArgumentException在方法的开头 如下所示 method body
  • 为什么 Parsec 的 sepBy 停止并且不解析所有元素?

    我正在尝试解析一些逗号分隔的字符串 该字符串可能包含也可能不包含具有图像尺寸的字符串 例如 hello world 300x300 good bye world 我写了下面的小程序 import Text Parsec import qua
  • 低级挂钩/SetWindowsHookEx lParam 自动重复?

    在这里阅读 Windows PC 上如何实现键盘自动重复 https stackoverflow com questions 876852 how is keyboard auto repeat implemented on a windo
  • 什么样的函数被认为是“可组合的”?

    维基百科文章函数组合 计算机科学 https en wikipedia org wiki Function composition computer science says 就像数学中通常的函数组合一样 每个函数的结果作为下一个函数的参数
  • 在 Haskell 中增长数组

    我想在 Haskell 中实现以下 命令式 算法 给定一个序列对 e0 s0 e1 s1 e2 s2 en sn 其中 e 和 s 部分不一定是自然数不同的是 在每个时间步都会随机选择该序列的一个元素 例如 ei si 并根据 ei si
  • “函数是第一等值”这到底是什么意思?

    有人可以用一些很好的例子清楚地解释它吗 在解释函数式编程时 我在 Scala 中遇到了这句话 一流 并不是一个正式定义的概念 但它通常意味着一个实体具有三个属性 有可能used 不受限制 只要 普通 值可以 即从函数传递和返回 放入容器等
  • 将数据类型设置为 Kind * -> * 这不是函子

    布伦特 约尔吉类型分类百科全书 https www haskell org haskellwiki Typeclassopedia给出以下练习 举一个类型的例子 gt 不能将其制成 的实例Functor 不使用undefined 请告诉我什
  • 我应该在 Turtle 或 Foldl 包中使用折叠吗?

    我在使用 Turtle 时遇到了一些困难 直到盯着难以理解的错误消息几分钟后才意识到我使用了错误的fold功能 https hackage haskell org package turtle 1 5 8 docs Turtle Shell
  • C 或 C++ 中未初始化的指针有用途吗?

    在其中一篇评论中这个问题 https stackoverflow com questions 1910832 c why arent pointers initialized with null by default 有人指出默认初始化 C
  • 持久 selectList 导致错误“无法将类型‘BaseBackend backend0’与‘SqlBackend’匹配”

    我遇到以下编译错误 Couldn t match type BaseBackend backend0 with SqlBackend arising from a use of runSqlite The type variable bac
  • 纯函数怎么能做IO呢?

    我最近了解到莫纳德随机数 http hackage haskell org package MonadRandom 0 1 13 docs Control Monad Random Class html t 3aMonadRandom图书馆
  • 指向指针的指针与普通指针

    指针的作用是保存特定变量的地址 那么下面代码的内存结构应该是这样的 int a 5 int b a 内存地址 值一个 0x000002 5b 0x000010 0x000002 好的 那么假设现在我要保存指针 b的地址 那么我们一般定义一个
  • 在这种情况下 b 是标量对象吗?

    include
  • 将两个 Int 值相除以获得 Float 的正确方法是什么?

    我想分两份IntHaskell 中的值并获得结果Float 我尝试这样做 foo Int gt Int gt Float foo a b fromRational a b 但 GHC 版本 6 12 1 告诉我 无法将预期类型 Intege

随机推荐

  • Flutter SharedPreferences如何加载所有保存的?

    如何加载 SharedPreferences 中保存的所有内容 我保存了很多布尔值 需要将所有布尔值加载到列表中 这就是我保存的方式 SharedPreferences sharedPreferences bool isfavorit ov
  • T-SQL 分割字符串

    我有一个 SQL Server 2008 R2 列 其中包含一个需要用逗号分隔的字符串 我在 StackOverflow 上看到了很多答案 但没有一个在 R2 中有效 我已确保我对任何拆分函数示例具有选择权限 非常感谢任何帮助 我之前用过这
  • R中Box Cox变换故障排除(需要使用for循环或apply)

    请在下面找到我的数据 行是疾病组 0 对照 1 溃疡性结肠炎和 2 克罗恩病 列是基因表达值 structure c 5 54312e 05 5 6112e 06 9 74312e 05 1 3612e 06 1 29312e 05 7 2
  • R 中 nlme 线性混合模型中相互作用显着性的检验

    I use lme函数在nlme用于测试因子水平的 R 包items与因子水平有显着的交互作用condition 因素condition有两个级别 Control and Treatment 以及因子items有 3 个级别 E1 E3 我
  • 如何在ubuntu-18.04上安装nexus

    我需要帮助在 ubuntu 18 04 上安装 nexus oss 我在互联网上找不到任何 apt get 命令 我尝试在 sudo apt get search nexus 中搜索nexus包 但无法获得正确的nexus版本包 我在网上浏
  • Bootstrap Affix 插件内存泄漏

    这些行 https github com twbs bootstrap blob master js affix js L19 L21在引导程序词缀插件中似乎会导致内存泄漏 因为窗口获取对从未释放的词缀实例的引用 作为解决方法 我使用此代码
  • OpenAPI 生成器的 Gradle 配置

    当将 OpenAPI 生成器与 Gradle 一起使用时 我希望将性别源发送到其他源生成器插件使用的标准目录 类似 Maven 生成源的东西 到目前为止 我还无法做到这一点 特别是限制生成 Java 源类而不是整个 原型项目 看来 Open
  • 在 AVX 寄存器内循环字节的有效方法

    摘要 tl 博士 除了进行 2 倍移位并将结果混合在一起之外 还有什么方法可以按位旋转 YMM 寄存器中的字节 使用 AVX 对于 YMM 寄存器中的每 8 个字节 我需要向左旋转 7 个字节 每个字节都需要比前一个字节向左旋转一位 因此
  • 如何为 SASS 变量中的 fs-* 类自定义 Bootstrap 5 字体大小

    如何更改 Bootstrap 5fs 上课于sass 因为在文档 https getbootstrap com docs 5 0 utilities text variables仅显示如何修改h 类如h5 font size 但不是fs c
  • Spring MVC:如何修改从控制器发送的json响应

    我已经使用如下控制器构建了一个 json REST 服务 Controller RequestMapping value scripts public class ScriptController Autowired private Scr
  • 64 位 Windows API:C/C++“DWORD”的大小是多少?

    我只安装了 32 位 Windows 因此我无法亲自验证这一点 如果我没理解错的话 微软API中各个地方使用的DWORD都是参考原来的16位字 和现在的硬件架构无 关 那么 即使我最终编译并链接我的应用程序以在 64 位 Windows 中
  • 有没有办法从 UITableView 中删除分隔线?

    我正在寻找一种在普通模式下完全删除 UITableView 中的分隔线的方法 这是在分组中自动完成的 但这也会以难以测量的方式改变表格的尺寸 我已将分隔线颜色设置为 colorClear 但这并不能完全解决问题 当我尝试在单元格中绘制自定义
  • 将文本文件中的数据读入 VBA 数组

    我有以下 VBA 代码 Sub read in data from txt file Dim dataArray As String Dim i As Integer Const strFileName As String Z sample
  • 使用 Common Lisp 进行排序时出现意外的列表重复

    编辑 解决方案是将第一个 let 形式中的 1 替换为 list 1 这是因为我试图修改文字数据 谢谢您的帮助 我会投赞成票 但显然你需要 15 声望 这是我在这个网站上的第一篇文章 我正在解决一些欧拉计划 https projecteul
  • 如何结合Flyway处理不在序列中的分支的合并

    我刚刚遇到了以下情况 测试服务器当前正在运行 Flyway 版本 1 V1 每当有任何内容推送到测试服务器上时 测试服务器都会自动更新 包括 Flyway 脚本 develop branch 开发人员决定开始在分支上开发新功能feature
  • 根据一组条件将数据框中的值替换为其他数据框中的值

    在 df1 中 我需要将 msec 的值替换为 df2 中的相应值 df1 lt data frame ID c rs rs rs tr tr tr cond c 1 1 2 1 1 2 block c 2 2 4 2 2 4 correc
  • 为什么我不能“转到默认值”或“转到案例 x;”在开关选择结构内?

    C11 第 6 8 1 节 http www iso 9899 info n1570 html 6 8 1 or C99 http www iso 9899 info n1256 html 6 8 1 或第 3 6 1 节C89 http
  • Android:我应该以什么方式将代码与样式分开?

    从 html php css 开始 Android 编程 我在网上搜索了一种将代码与样式分开的简单方法 现在我需要在列表或表格视图中显示数据库中的数据 简而言之 我从数据库获取一个游标 迭代它 在代码中动态创建每个列表项作为 TextVie
  • 如何在 leiningen repl 中预加载 clojure 文件?

    我希望在启动 clojure REPL 时预加载一些 clojure 函数 这些函数没有多大用处 除非您在 REPL 上下文中使用它们 如果有帮助 我通常使用 leiningen 为我启动 clojure REPL 我如何告诉 clojur
  • 函数是如何柯里化的?

    我了解柯里化的概念是什么 并且知道如何使用它 这些不是我的问题 而是我很好奇这是如何在比 Haskell 代码更低的级别上实际实现的 例如 当 2 4被柯里化 是一个指向2维持直到4被传入 甘道夫会扭曲时空吗 这是什么魔法 简短回答 是的