Haskell 中的所有图形和 Web 库是如何实现的?

2024-06-20

我才开始学习Haskell。我读到它是一种纯函数式语言,其中的所有内容都是不可变的。因此,输入输出、写入和读取数据库之类的事情会导致状态的可变性。我知道 Haskell 中有一种叫做 monad 的东西,它允许在 Haskell 中使用命令式功能,例如IO Monad。但我有趣的是 Haskell 中的所有命令都是在 monad 的帮助下实现的吗? HackageDB 上有很多软件包可以处理 3D 图形、数据库、解析 HTML、编写 Web 服务器等等。

这一切背后的总体想法是什么?是什么让 Haskell 既能保持纯粹,又能适用于编写这一切?我希望有人能为我澄清这一点。提前致谢!


我通过以下类比来理解这些事情,我将用 JavaScript 来表达。

如何表达一种副作用计算?

1. 一个函数

这显然是我首先想到的:

var launchRockets = function () {
  prepareRockets( queryDBForPreparationParameters() )
  launchAllPreparedRockets()
  outputResults()
}

您可以看到一个有效的函数调用了一堆其他有效的函数,这些函数本身可以产生未知的效果以及随之而来的所有后果。

2. 使用说明

表达这一点的另一种方法是编写一组指令来描述某些函数稍后执行的有效计算。 (曾经编写过 SQL 查询吗?)

var launchRocketsInstructions = [
  {
    description: "Prepare rockets",
    parameters: {
      description: "Query a DB for preparation parameters"
    }
  },
  {
    description: "Launch all prepared rockets"
  },
  {
    description: "Output results"
  }
]

那么我们在第二个例子中看到了什么?我们看到一个不可变的数据树描述计算而不是立即执行它。这里没有副作用,为了构建这个数据树,我们当然可以使用纯函数。这就是 Haskell 中副作用的本质。该语言提供的所有基础设施:单子、IO, the do-符号-这些只是工具和抽象,可以简化您编写单个指令树的任务。

当然,要真正执行这些指令,人们最终必须逃入副作用的狂野世界。如果是 JavaScript,它会是这样的execute(launchRocketsInstructions),对于 Haskell 来说,它是执行用函数生成的指令树根的运行时main主模块的主模块,它成为程序的单一入口点。因此,Haskell 中的副作用实际上发生在语言范围之外,这就是它是纯粹的原因。

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

Haskell 中的所有图形和 Web 库是如何实现的? 的相关文章

随机推荐