如何在纯函数式编程中产生副作用?

高洛·罗登(Golo Roden)

我处理函数编程的概念已有一段时间了,发现它很有趣,令人着迷且令人兴奋。特别是纯函数的概念在各个方面都很棒。

但是我没有一件事:将自己限制为纯函数时如何处理副作用。

例如,如果我想计算两个数字的和,则可以编写一个纯函数(在JavaScript中):

var add = function (first, second) {
  return first + second;
};

没问题。但是,如果我想将结果打印到控制台怎么办?从定义上讲,“将某些内容打印到控制台”的任务不是纯粹的-但是我应该/应该如何用一种纯函数式编程语言来处理呢?

q

有几种方法可以做到这一点。您将不得不接受的一件事是,在某个时刻,存在着一种神奇的不纯机器,该机器采用纯表达式并通过与环境交互来使它们不纯。您不应该问关于这个神奇机器的问题。

我可以想到两种方法。我至少已经忘记了第三个人。


I / O流

最容易理解的方法可能是流I / O。您的main函数有一个参数:系统上发生的一系列事件–包括按键,文件系统上的文件等等。您的main函数还返回一件事:您希望在系统上发生的一系列事情。

请注意,流就像列表一样,一次只能创建一个元素,而接收者在构建元素后会立即收到它。您的纯程序从此类流中读取,并在希望系统执行某些操作时将其追加到其自己的流中。

完成所有这些工作的粘合剂是一台神奇的机器,它位于程序之外,从“请求”流中读取内容并将内容放入“答案”流中。虽然您的程序是纯程序,但是这台神奇的机器却不是。

输出流看起来像这样:

[print('Hello, world! What is your name?'), input(), create_file('G:\testfile'), create_file('C:\testfile'), write_file(filehandle, 'John')]

并且相应的输入流将是

['John', IOException('There is no drive G:, could not create file!'), filehandle]

看看插播广告是如何input导致'John'出现在插播广告中的?这就是原则。

单声道I / O

Haskell所做的就是Monadic I / O,而且确实做得很好。您可以想象这就像用操作员构建一棵巨大的I / O命令树将它们粘合在一起,然后您的main函数将这个庞大的表达式返回到位于程序外部的神奇机器上,并执行命令并执行指示的操作。这台神奇的机器是不纯洁的,而您的表情构建程序却是纯洁的。

您可能想像一下此命令树看起来像

main
  |
  +---- Cmd_Print('Hello, world! What is your name?')
  +---- Cmd_WriteFile
           |
           +---- Cmd_Input
           |
           +---+ return validHandle(IOResult_attempt, IOResult_safe)
               + Cmd_StoreResult Cmd_CreateFile('G:\testfile') IOResult_attempt
               + Cmd_StoreResult Cmd_CreateFile('C:\testfile') IOResult_safe

它要做的第一件事是打印问候语。接下来要做的是它要写入一个文件。为了能够写入文件,它首先需要从输入中读取应该写入文件的任何内容。然后应该有一个要写入的文件句柄。它从一个称为函数的函数获取此函数,该函数validHandle返回两个替代方案的有效句柄。这样,您可以将看似不纯的代码与看似纯代码的内容混合在一起。


这个“解释”几乎是在问关于您不应该问的神奇机器的问题,因此,我将用一些智慧总结一下。

  • 真正的Monadic I / O在我的示例中看起来很遥远。我的示例是有关单子I / O在不破坏纯度的情况下看起来像“引擎盖下”的可能解释之一。

  • 千万不能尝试使用我的例子来说明如何理解与纯粹的I / O工作。事物在幕后的工作方式与您使用事物做事的方式完全不同。如果您一生中从未见过汽车,那么阅读其中任何一个的蓝图都不会成为一名好司机。

    我一直说你不应该问关于真正起作用的神奇机器的问题的原因是,当程序员学习东西时,他们倾向于戳破机器以试图弄清楚它。我不建议您将其用于纯I / O。该机器可能不会教您任何有关如何使用不同I / O变体的知识。

    这类似于您通过查看反汇编的JVM字节码而不学习Java的方式。

  • 一定要学习使用monadic I / O和基于流的I / O。这是一次很酷的体验,在您的工具带下拥有更多的工具总是一件好事。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在函数式编程中如何避免副作用

来自分类Dev

函数式编程的副作用(球拍)

来自分类Dev

如何在html中产生X标记。

来自分类Dev

如何在Java中产生True UUID?

来自分类Dev

如何在PHP中产生销售数量

来自分类Dev

如何在Wildfly中产生SessionContext

来自分类Dev

如何在PHP中产生404错误?

来自分类Dev

如何在Excel中产生重复?

来自分类Dev

如何在html中产生X标记。

来自分类Dev

如何在猪中产生重复群?

来自分类Dev

如何在底层实现函数式编程?

来自分类Dev

使用 Result 在控制流中产生副作用的推荐方法是什么?

来自分类Dev

了解Haskell中的纯函数和副作用-putStrLn

来自分类Dev

如何在首次订阅创建和最后一次订阅处置时产生副作用?

来自分类Dev

如何使用JavaScript中的“纯”函数式编程实现备忘录

来自分类Dev

如何测试产生误差的方法的副作用

来自分类Dev

如何在Matlab符号方程式中产生方波

来自分类Dev

如何在Linux上的C语言中产生声音?

来自分类Dev

ggplot:如何在geom_polygon中产生渐变填充

来自分类Dev

如何在数组中产生行空间

来自分类Dev

如何在Python中产生JSON格式的Kafka消息

来自分类Dev

malloc如何在C中产生列表的元素?

来自分类Dev

如何在php中产生postgresql日期输出?

来自分类Dev

我如何在pygame中产生多个敌人

来自分类Dev

如何在R中产生按年计算的列

来自分类Dev

这个javascript类大纲是如何在Visual Studio中产生的?

来自分类Dev

如何在整个表格行中产生熄灭效果

来自分类Dev

如何在C中的mergesort中产生最坏的情况?

来自分类Dev

如何在Matlab符号方程中产生方波