Как все графические и веб-библиотеки реализованы в Haskell?
Я только начинаю изучать Haskell. Я читал, что это чисто функциональный язык, и все в нем является неизменным. Таким образом, такие вещи, как ввод, вывод и запись баз данных, вызывают изменчивость состояния. Я знаю, что в Haskell есть такая вещь, как монады, которые позволяют использовать императивные функции в Haskell, такие как IO Monad
, Но мне интересно, все ли императивно в Haskell реализовано с помощью монад? На HackageDB есть много пакетов, которые позволяют работать с 3d-графикой, базами данных, анализировать HTML, писать веб-серверы и так далее и тому подобное.
Какая общая идея стоит за всем этим? Что позволяет Haskell оставаться чистым и одновременно подходящим для написания всего этого? Я надеюсь, что кто-нибудь прояснит это для меня. Заранее спасибо!
4 ответа
Я понял эти вещи, используя следующую аналогию, которую я изложу с помощью 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
, do
-notation - это всего лишь инструменты и абстракции, упрощающие задачу составления единого дерева инструкций.
Конечно, чтобы действительно выполнить эти инструкции, нужно в конечном итоге сбежать в дикий мир побочных эффектов. В случае JavaScript это было бы что-то вроде execute(launchRocketsInstructions)
, в случае Haskell это среда выполнения, выполняющая корень дерева команд, которое вы производите с помощью функции main
основного модуля, который становится единой точкой входа вашей программы. Таким образом, побочные эффекты в Haskell на самом деле возникают вне языковой области, поэтому они чистые.
Я читал, что это чисто функциональный язык, и все в нем является неизменным.
Haskell только чистый / по умолчанию /. Если вы объявляете компилятору (через монадический тип), что вы хотите иметь определенные эффекты, тогда они включены.
Они просто не включены по умолчанию.
В Хаскеле вы никогда ничего не исполняете. Вы просто создаете описание того, что вы хотите сделать, комбинируя действия ввода-вывода, а затем назначаете это описание main. Затем компилятор переводит любое найденное в основной переменной описание программы в исполняемый код.
Я рекомендую вам прочитать это введение в Haskell IO, которое я написал, в котором все изложено более подробно.
Однако это только объясняет, как мы объединяем действия ввода-вывода, а не то, как мы вводим новые. У Haskell есть два способа добавить новые действия ввода-вывода:
- Встроенные компиляторы
- Интерфейс внешней функции (FFI)
Тогда все, что делает монада IO - это объединяет эти примитивные действия IO в более крупные действия IO.
Да, все, что необходимо в Хаскеле, написано с помощью монад. Монады - это общая идея, которая позволяет Haskell быть как чистым, так и применимым для написания практических программ, которые выполняют реальный ввод-вывод.
Я рекомендую прочесть известную статью Саймона Пейтона Джонса "Tackling the Awkward Squad", в которой объясняется, как монада IO используется для программирования в реальном мире на чисто функциональном языке.