Haskell中的所有图形和网络库如何实现?

我只开始学习Haskell。 我读过它是一种纯粹的函数式语言,其中的一切都是不变的。 因此,诸如输入输出,写入和读取数据库等事情会导致状态的可变性。 我知道Haskell中有一个叫做monad的东西,它允许像IO Monad一样使用Haskell中的命令式功能。 但我很感兴趣的是Haskell中的一切都是在单子的帮助下实现的? 在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本质上的副作用。 语言提供的所有基础设施:monads, IOdo -notation - 这些只是工具和抽象,简化了您编写单一指令树的任务。

当然,要实际执行这些指令,人们最终必须逃避到野外的副作用世界。 在JavaScript的情况下,它会是这样execute(launchRocketsInstructions)在Haskell的情况下,执行你生产出功能指令树的根运行main主模块,它成为你的程序的单一入口点。 因此,Haskell的副作用实际上发生在语言范围之外,这就是为什么它是纯粹的。


我读过它是一种纯粹的函数式语言,其中的一切都是不变的。

Haskell只是纯粹的/默认情况下。 如果您向编译器声明(通过一元类型)您希望获得特定效果,则会启用它们。

他们只是默认情况下不开启。


在Haskell中,你永远不会执行任何事情。 您只需将IO操作组合起来,然后将该描述分配给main,即可构建您想要执行的操作的描述。 然后编译器将它在主变量中找到的任何程序描述转换为可执行代码。

我建议你阅读我写的Haskell IO的这个介绍,它更详细地描述了事情。

但是,这只解释了我们如何结合IO操作而不是如何引入新操作。 Haskell有两种方法来添加新的IO操作:

  • 编译器内置程序
  • 外部功能接口(FFI)
  • 然后,所有IO monad所做的就是将这些原始IO操作组合成更大的IO操作。

    链接地址: http://www.djcxy.com/p/14195.html

    上一篇: How are all graphic and web libraries implemented in Haskell?

    下一篇: F# advanced exercises