Passed after some naive grammar checker.
This commit is contained in:
parent
4a61dbb8fc
commit
420c6c6a41
6 changed files with 17 additions and 15 deletions
|
@ -3,7 +3,7 @@
|
||||||
In my
|
In my
|
||||||
[preceding article](/Scratch/en/blog/Haskell-the-Hard-Way/) I introduced Haskell.
|
[preceding article](/Scratch/en/blog/Haskell-the-Hard-Way/) I introduced Haskell.
|
||||||
|
|
||||||
This article go further.
|
This article goes further.
|
||||||
It will show how to use functional programming with interactive programs.
|
It will show how to use functional programming with interactive programs.
|
||||||
But more than that, it will show how to organize your code in a functional way.
|
But more than that, it will show how to organize your code in a functional way.
|
||||||
This article is more about functional paradigm than functional language.
|
This article is more about functional paradigm than functional language.
|
||||||
|
@ -14,18 +14,18 @@ In reality, the firsts sections will use an imperative paradigm.
|
||||||
As you can use functional paradigm in imperative language,
|
As you can use functional paradigm in imperative language,
|
||||||
you can also use imperative paradigm in functional languages.
|
you can also use imperative paradigm in functional languages.
|
||||||
|
|
||||||
This article is about creating a useful and clean program.
|
This article is about creating an useful and clean program.
|
||||||
It can interact with the user in real time.
|
It can interact with the user in real time.
|
||||||
It uses OpenGL, a library with imperative programming foundations.
|
It uses OpenGL, a library with imperative programming foundations.
|
||||||
But the final code will be quite clean.
|
Despite this fact,
|
||||||
Most of the code will remain in the pure part (no `IO`).
|
most of the final code will remain in the pure part (no `IO`).
|
||||||
|
|
||||||
I believe the main audience for this article are:
|
I believe the main audience for this article are:
|
||||||
|
|
||||||
- Haskell programmer looking for an OpengGL tutorial.
|
- Haskell programmer looking for an OpengGL tutorial.
|
||||||
- People interested in program organization (programming language agnostic).
|
- People interested in program organization (programming language agnostic).
|
||||||
- Fractal lovers and in particular 3D fractal.
|
- Fractal lovers and in particular 3D fractal.
|
||||||
- Game programmers (any language)
|
- People interested in user interaction in a functional paradigm.
|
||||||
|
|
||||||
I had in mind for some time now to make a Mandelbrot set explorer.
|
I had in mind for some time now to make a Mandelbrot set explorer.
|
||||||
I had already written a [command line Mandelbrot set generator in Haskell](http://github.com/yogsototh/mandelbrot.git).
|
I had already written a [command line Mandelbrot set generator in Haskell](http://github.com/yogsototh/mandelbrot.git).
|
||||||
|
@ -33,7 +33,8 @@ This utility is highly parallel; it uses the `repa` package[^001].
|
||||||
|
|
||||||
[^001]: Unfortunately, I couldn't make this program to work on my Mac. More precisely, I couldn't make the [DevIL](http://openil.sourceforge.net/) library work on Mac to output the image. Yes I have done a `brew install libdevil`. But even a minimal program who simply write some `jpg` didn't worked. I tried both with `Haskell` and `C`.
|
[^001]: Unfortunately, I couldn't make this program to work on my Mac. More precisely, I couldn't make the [DevIL](http://openil.sourceforge.net/) library work on Mac to output the image. Yes I have done a `brew install libdevil`. But even a minimal program who simply write some `jpg` didn't worked. I tried both with `Haskell` and `C`.
|
||||||
|
|
||||||
This time, we will display the Mandelbrot set extended in 3D using OpenGL and Haskell.
|
This time, we will not parallelize the computation.
|
||||||
|
Instead, we will display the Mandelbrot set extended in 3D using OpenGL and Haskell.
|
||||||
You will be able to move it using your keyboard.
|
You will be able to move it using your keyboard.
|
||||||
This object is a Mandelbrot set in the plan (z=0),
|
This object is a Mandelbrot set in the plan (z=0),
|
||||||
and something nice to see in 3D.
|
and something nice to see in 3D.
|
||||||
|
|
|
@ -18,7 +18,7 @@ And the second part more focused on OpenGL and content.
|
||||||
> import Graphics.UI.GLUT
|
> import Graphics.UI.GLUT
|
||||||
> import Data.IORef
|
> import Data.IORef
|
||||||
|
|
||||||
For efficiency reason, I won't use the default Haskell `Complex` data type.
|
For efficiency reason, I will not use the default Haskell `Complex` data type.
|
||||||
|
|
||||||
> newtype Complex = C (Float,Float) deriving (Show,Eq)
|
> newtype Complex = C (Float,Float) deriving (Show,Eq)
|
||||||
|
|
||||||
|
@ -168,13 +168,13 @@ This property is a direct consequence of purity.
|
||||||
If you look closely, you see that `allPoints` is a pure list.
|
If you look closely, you see that `allPoints` is a pure list.
|
||||||
Therefore, calling `allPoints` will always render the same result and Haskell is clever enough to use this property.
|
Therefore, calling `allPoints` will always render the same result and Haskell is clever enough to use this property.
|
||||||
While Haskell doesn't garbage collect `allPoints` the result is reused for free.
|
While Haskell doesn't garbage collect `allPoints` the result is reused for free.
|
||||||
We didn't specified this value should be saved for later use.
|
We did not specified this value should be saved for later use.
|
||||||
It is saved for us.
|
It is saved for us.
|
||||||
|
|
||||||
See what occurs if we make the window bigger:
|
See what occurs if we make the window bigger:
|
||||||
|
|
||||||
blogimage("hglmandel_v01_too_wide.png","The mandelbrot too wide, black lines and columns")
|
blogimage("hglmandel_v01_too_wide.png","The mandelbrot too wide, black lines and columns")
|
||||||
|
|
||||||
We see some black lines because we drawn less point than there is on the surface.
|
We see some black lines because we have drawn less point than there is on the surface.
|
||||||
We can repair this by drawing little squares instead of just points.
|
We can repair this by drawing little squares instead of just points.
|
||||||
But, instead we will do something a bit different and unusual.
|
But, instead we will do something a bit different and unusual.
|
||||||
|
|
|
@ -50,10 +50,11 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
This time, instead of drawing all points, I'll simply want to draw the edges of the Mandelbrot set.
|
This time, instead of drawing all points,
|
||||||
|
we will simply draw the edges of the Mandelbrot set.
|
||||||
The method I use is a rough approximation.
|
The method I use is a rough approximation.
|
||||||
I consider the Mandelbrot set to be almost convex.
|
I consider the Mandelbrot set to be almost convex.
|
||||||
The result will be good enough.
|
The result will be good enough for the purpose of this tutorial.
|
||||||
|
|
||||||
We change slightly the `drawMandelbrot` function.
|
We change slightly the `drawMandelbrot` function.
|
||||||
We replace the `Points` by `LineLoop`
|
We replace the `Points` by `LineLoop`
|
||||||
|
|
|
@ -184,7 +184,7 @@ and `(-0.5)` is the number `-0.5` (yes I share your pain).
|
||||||
> -- any other keys does nothing
|
> -- any other keys does nothing
|
||||||
> kact _ _ _ _ _ = return ()
|
> kact _ _ _ _ _ = return ()
|
||||||
|
|
||||||
Note `display` take some parameters this time.
|
Note `display` takes some parameters this time.
|
||||||
This function if full of boilerplate:
|
This function if full of boilerplate:
|
||||||
|
|
||||||
> display angle zoom position = do
|
> display angle zoom position = do
|
||||||
|
|
|
@ -34,7 +34,7 @@ functionalMainLoop =
|
||||||
Clearly, ideally we should provide only three parameters to this main loop function:
|
Clearly, ideally we should provide only three parameters to this main loop function:
|
||||||
|
|
||||||
- an initial World state
|
- an initial World state
|
||||||
- a mapping between the user interaction and function which modify the world
|
- a mapping between the user interactions and functions which modify the world
|
||||||
- a function taking two parameters: time and world state and render a new world without user interaction.
|
- a function taking two parameters: time and world state and render a new world without user interaction.
|
||||||
|
|
||||||
Here is a real working code, I've hidden most display functions.
|
Here is a real working code, I've hidden most display functions.
|
||||||
|
|
|
@ -23,9 +23,9 @@ begindiv(intro)
|
||||||
en: %tldr A progressive Haskell example.
|
en: %tldr A progressive Haskell example.
|
||||||
en: A Mandelbrot set extended in 3D, rendered using OpenGL and coded with Haskell.
|
en: A Mandelbrot set extended in 3D, rendered using OpenGL and coded with Haskell.
|
||||||
en: In the end the code will be very clean.
|
en: In the end the code will be very clean.
|
||||||
en: The meaningful stuff will be in a pure functional bubble.
|
en: The significant stuff will be in a pure functional bubble.
|
||||||
en: The display details will be put in an external module playing the role of a wrapper.
|
en: The display details will be put in an external module playing the role of a wrapper.
|
||||||
en: You'll can use this kind of functional organization even in imperative language.
|
en: Imperative language could also benefit from this functional organization.
|
||||||
fr: %tlal Un exemple progressif d'utilisation d'Haskell.
|
fr: %tlal Un exemple progressif d'utilisation d'Haskell.
|
||||||
fr: Vous pourrez voir un ensemble de Mandelbrot étendu à la troisième dimension.
|
fr: Vous pourrez voir un ensemble de Mandelbrot étendu à la troisième dimension.
|
||||||
fr: De plus le code sera très propre.
|
fr: De plus le code sera très propre.
|
||||||
|
|
Loading…
Reference in a new issue