问题
I only begin to learn Haskell. I've read that it is a pure functional language and everything in it is immutable. So things like input output, writing and reading databases cause mutability of the state. I know there is a thing in Haskell called monads which allow to use imperative features in Haskell like IO Monad
. But I'm interesting is everything imperative in Haskell is implemented with the help of monads? On the HackageDB there are a lot of packages which allow to work with 3d-graphics, databases, parse HTML, write web servers and so on and so forth.
What is the general idea behind all of this? What does allow Haskell to remain pure and simultaneously be applicable for writing all this? I hope somebody will make this clear for me. Thanks in advance!
回答1:
I came to understand these things using the following analogy, which I'll express with JavaScript.
How can one express a side-effecting computation?
1. A function
That is obviously a first thing comming to mind:
var launchRockets = function () {
prepareRockets( queryDBForPreparationParameters() )
launchAllPreparedRockets()
outputResults()
}
You can see an effectful function calling a bunch of other effectful functions, which themselves can produce unknown effects with all the ensuing consequences.
2. Instructions
Another way to express this would be to compose a set of instructions describing those effectful computations for some function to later execute. (Ever composed an SQL query?)
var launchRocketsInstructions = [
{
description: "Prepare rockets",
parameters: {
description: "Query a DB for preparation parameters"
}
},
{
description: "Launch all prepared rockets"
},
{
description: "Output results"
}
]
So what do we see in our second example? We see an immutable data tree describing the computation instead of performing it right away. There are no side effects here, and for composing this data tree we can surely use pure functions. And that's what essentially side effects are all about in Haskell. All the infrastructure the language provides: the monads, the IO
, the do
-notation - these are just tools and abstractions simplifying your task of composing a single tree of instructions.
Of course to actually perform these instructions one will have to eventually escape into the wild world of side-effects. In case of JavaScript it would be something like execute(launchRocketsInstructions)
, in case of Haskell it is the runtime executing the root of the instruction tree which you produce with the function main
of the main module, which becomes the single entry point of your program. Thereby the side effects in Haskell actually occur outside of the language scope, that's why it's pure.
回答2:
I've read that it is a pure functional language and everything in it is immutable.
Haskell is only pure /by default/. If you declare to the compiler (via a monadic type) that you wish to have certain effects, then they are enabled.
They're just not on by default.
回答3:
In Haskell you never actually execute anything. You simply build up a description of what you wish to do by combining IO actions and then assign that description to main. The compiler then translates whatever program description it finds in the main variable to executable code.
I recommend you read this introduction to Haskell IO I wrote which spells things out in greater detail.
However, that only explains how we combine IO actions and not how we introduce new ones. Haskell has two ways to add new IO actions:
- Compiler built-ins
- The Foreign Function Interface (FFI)
Then all the IO monad does is combine those primitive IO actions into larger IO actions.
回答4:
Yes, everything imperative in Haskell is written with the help of monads. Monads are the the general idea that allows Haskell to be both pure and applicable for writing practical programs that do real-world I/O.
I recommend reading the famous paper "Tackling the Awkward Squad" by Simon Peyton Jones, which explains how the IO monad is used to do real-world programming in a pure-functional language.
来源:https://stackoverflow.com/questions/15834966/how-are-all-graphic-and-web-libraries-implemented-in-haskell