Added images, fixed syntax highlighting
|
@ -237,9 +237,9 @@ figure, .figure {
|
||||||
--o: #aa6550;
|
--o: #aa6550;
|
||||||
--r: #b85a64;
|
--r: #b85a64;
|
||||||
--m: #af53b0;
|
--m: #af53b0;
|
||||||
--violet: #846f93;
|
--v: #846f93;
|
||||||
--b: #5679a4;
|
--b: #5679a4;
|
||||||
--cyan: #4c8493;
|
--c: #4c8493;
|
||||||
--g: #728b5c;
|
--g: #728b5c;
|
||||||
|
|
||||||
/* Solaryzed accented colors */
|
/* Solaryzed accented colors */
|
||||||
|
@ -438,7 +438,7 @@ blockquote:after, .main blockquote:after {
|
||||||
}
|
}
|
||||||
|
|
||||||
.org-rainbow-delimiters-depth-2, .org-nix-builtin, .org-variable-name,
|
.org-rainbow-delimiters-depth-2, .org-nix-builtin, .org-variable-name,
|
||||||
.org-function-name, .org-diff-changed {
|
.org-haskell-definition, .org-haskell-operator, .org-function-name, .org-diff-changed {
|
||||||
color:var(--b);
|
color:var(--b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,11 +453,11 @@ blockquote:after, .main blockquote:after {
|
||||||
.org-rainbow-delimiters-depth-5, .org-diff-removed, .TODO {
|
.org-rainbow-delimiters-depth-5, .org-diff-removed, .TODO {
|
||||||
color:var(--r);
|
color:var(--r);
|
||||||
}
|
}
|
||||||
.org-rainbow-delimiters-depth-6 {
|
.org-rainbow-delimiters-depth-6, .org-haskell-constructor {
|
||||||
color:var(--o);
|
color:var(--o);
|
||||||
}
|
}
|
||||||
.org-rainbow-delimiters-depth-7, .org-type, .org-constant, .org-diff-header,
|
.org-rainbow-delimiters-depth-7, .org-type, .org-constant, .org-diff-header,
|
||||||
.IN_PROGRESS {
|
.org-haskell-keyword, .org-haskell-type, .IN_PROGRESS {
|
||||||
color:var(--y);
|
color:var(--y);
|
||||||
}
|
}
|
||||||
.org-rainbow-delimiters-depth-8, .org-sh-heredoc, .org-diff-added, .org-string,
|
.org-rainbow-delimiters-depth-8, .org-sh-heredoc, .org-diff-added, .org-string,
|
||||||
|
@ -472,6 +472,7 @@ blockquote:after, .main blockquote:after {
|
||||||
color:var(--fg2);
|
color:var(--fg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.org-highlight-number-number {
|
.org-highlight-numbers-number, .org-highlight-number-number
|
||||||
|
{
|
||||||
color:var(--rfg);
|
color:var(--rfg);
|
||||||
}
|
}
|
||||||
|
|
BIN
src/posts/0010-Haskell-Now/Haskell-logo.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
src/posts/0010-Haskell-Now/dali_reve.jpg
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
src/posts/0010-Haskell-Now/dangerous_book.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
src/posts/0010-Haskell-Now/escher_infinite_lizards.jpg
Normal file
After Width: | Height: | Size: 134 KiB |
BIN
src/posts/0010-Haskell-Now/escher_polygon.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
src/posts/0010-Haskell-Now/golconde.jpg
Normal file
After Width: | Height: | Size: 98 KiB |
After Width: | Height: | Size: 53 KiB |
|
@ -1,33 +1,29 @@
|
||||||
#+title: Learn Haskell Fast and Hard
|
#+title: Learn Haskell Fast and Hard
|
||||||
#+subtitle: Blow your mind with Haskell
|
#+subtitle: Blow your mind with Haskell
|
||||||
#+date: [2012-02-08]
|
#+date: [2019-12-15 Sun]
|
||||||
#+author: Yann Esposito
|
#+author: Yann Esposito
|
||||||
#+EMAIL: yann@esposito.host
|
#+EMAIL: yann@esposito.host
|
||||||
#+keywords: Haskell, programming, functional, tutorial |
|
#+keywords: Haskell, programming, functional, tutorial |
|
||||||
#+DESCRIPTION: Meta article about how I generate this blog.
|
#+DESCRIPTION: Haskell programming tutorial update
|
||||||
#+OPTIONS: auto-id:t toc:t
|
#+OPTIONS: auto-id:t toc:t
|
||||||
|
|
||||||
#+begin_notes
|
#+begin_notes
|
||||||
A very short and dense tutorial for learning Haskell.
|
A very short and intense introduction to Haskell.
|
||||||
|
|
||||||
|
This is an update of my old (2012) article.
|
||||||
|
A lot of things have changed since then.
|
||||||
|
And I took the time to read it again.
|
||||||
#+end_notes
|
#+end_notes
|
||||||
|
|
||||||
Thanks to:
|
#+begin_quote
|
||||||
|
*Prelude*
|
||||||
|
|
||||||
- [[https://plus.google.com/u/0/113751420744109290534][Oleg Taykalo]]
|
In 2012, I really believed that every developer should learn Haskell.
|
||||||
you can find a Russian translation here:
|
It is the end of 2019 and I still believe it.
|
||||||
[[http://habrahabr.ru/post/152889/][Part 1]] /&/
|
I don't think everyone needs to be a super Haskell ninja, but they should
|
||||||
[[http://habrahabr.ru/post/153383/][Part 2]],
|
at least discover what Haskell has to offer.
|
||||||
- [[http://silly-bytes.blogspot.fr][Daniel Campoverde]] for the Spanish
|
Learning Haskell opens your mind.
|
||||||
translation here:
|
#+end_quote
|
||||||
[[http://silly-bytes.blogspot.fr/2016/06/aprende-haskell-rapido-y-dificil_29.html][Aprende
|
|
||||||
Haskell rápido y difícil]],
|
|
||||||
- [[http://github.com/joom][Joomy Korkut]] for the Turkish translation
|
|
||||||
here: [[https://github.com/joom/zor-yoldan-haskell][Zor Yoldan
|
|
||||||
Haskell]].
|
|
||||||
|
|
||||||
I really believe all developers should learn Haskell. I don't think
|
|
||||||
everyone needs to be super Haskell ninjas, but they should at least
|
|
||||||
discover what Haskell has to offer. Learning Haskell opens your mind.
|
|
||||||
|
|
||||||
Mainstream languages share the same foundations:
|
Mainstream languages share the same foundations:
|
||||||
|
|
||||||
|
@ -36,27 +32,32 @@ Mainstream languages share the same foundations:
|
||||||
- pointers[fn:1]
|
- pointers[fn:1]
|
||||||
- data structures, objects and classes (for most)
|
- data structures, objects and classes (for most)
|
||||||
|
|
||||||
Haskell is very different. The language uses a lot of concepts I had
|
Haskell is very different.
|
||||||
never heard about before. Many of those concepts will help you become a
|
The language uses a lot of concepts I had never heard about before.
|
||||||
better programmer.
|
Many of those concepts will help you become a better programmer.
|
||||||
|
|
||||||
But learning Haskell can be hard. It was for me. In this article I try
|
But learning Haskell can be hard.
|
||||||
to provide what I lacked during my learning.
|
It was for me.
|
||||||
|
In this article I try to provide as much help as possible to accelerate
|
||||||
|
your learning.
|
||||||
|
|
||||||
This article will certainly be hard to follow. This is on purpose. There
|
This article will certainly be hard to follow.
|
||||||
is no shortcut to learning Haskell. It is hard and challenging. But I
|
This is on purpose.
|
||||||
believe this is a good thing. It is because it is hard that Haskell is
|
There is no shortcut to learning Haskell.
|
||||||
interesting.
|
It is hard and challenging.
|
||||||
|
But I believe this is a good thing.
|
||||||
|
It is because it is hard that Haskell is interesting and rewarding.
|
||||||
|
|
||||||
The conventional method to learning Haskell is to read two books. First
|
Today, I could not really provide a conventional path to learn Haskell.
|
||||||
[[http://learnyouahaskell.com]["Learn You a Haskell"]] and just after
|
So I think the best I can do is point you to the [[https://www.haskell.org/documentation/][haskell.org]] documentation
|
||||||
[[http://www.realworldhaskell.org]["Real World Haskell"]]. I also
|
website.
|
||||||
believe this is the right way to go. But to learn what Haskell is all
|
And you will see that most path involve a quite long learning process.
|
||||||
about, you'll have to read them in detail.
|
By that, I mean that you should read a long book and invest a lot of hours
|
||||||
|
and certainly days before having a good idea about what Haskell is all about.
|
||||||
|
|
||||||
In contrast, this article is a very brief and dense overview of all
|
In contrast, this article is a very brief and dense overview of all
|
||||||
major aspects of Haskell. I also added some information I lacked while I
|
major aspects of Haskell.
|
||||||
learned Haskell.
|
I also added some information I lacked while I learned Haskell.
|
||||||
|
|
||||||
The article contains five parts:
|
The article contains five parts:
|
||||||
|
|
||||||
|
@ -80,20 +81,6 @@ The article contains five parts:
|
||||||
- More on infinite tree; a more math oriented discussion about
|
- More on infinite tree; a more math oriented discussion about
|
||||||
infinite trees
|
infinite trees
|
||||||
|
|
||||||
#+BEGIN_QUOTE
|
|
||||||
Note: Each time you see a separator with a filename ending in =.lhs=
|
|
||||||
you can click the filename to get this file. If you save the file as
|
|
||||||
=filename.lhs=, you can run it with
|
|
||||||
|
|
||||||
#+BEGIN_SRC
|
|
||||||
runhaskell filename.lhs
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
Some might not work, but most will. You should see a link just below.
|
|
||||||
#+END_QUOTE
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
* Introduction
|
* Introduction
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:CUSTOM_ID: introduction
|
:CUSTOM_ID: introduction
|
||||||
|
@ -104,7 +91,8 @@ The article contains five parts:
|
||||||
:CUSTOM_ID: install
|
:CUSTOM_ID: install
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
blogimage("Haskell-logo.png", "Haskell logo")
|
#+CAPTION: Haskell logo
|
||||||
|
[[./Haskell-logo.png]]
|
||||||
|
|
||||||
There are different way to install Haskell, I would recommend to use
|
There are different way to install Haskell, I would recommend to use
|
||||||
[[https://haskellstack.org][=stack=]].
|
[[https://haskellstack.org][=stack=]].
|
||||||
|
@ -124,7 +112,8 @@ Tools:
|
||||||
:CUSTOM_ID: don't-be-afraid
|
:CUSTOM_ID: don't-be-afraid
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
blogimage("munch_TheScream.jpg","The Scream")
|
#+CAPTION: The Scream
|
||||||
|
[[./munch_TheScream.jpg]]
|
||||||
|
|
||||||
Many books/articles about Haskell start by introducing some esoteric
|
Many books/articles about Haskell start by introducing some esoteric
|
||||||
formula (quick sort, Fibonacci, etc...). I will do the exact opposite.
|
formula (quick sort, Fibonacci, etc...). I will do the exact opposite.
|
||||||
|
@ -217,7 +206,8 @@ languages.
|
||||||
:CUSTOM_ID: very-basic-haskell
|
:CUSTOM_ID: very-basic-haskell
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
blogimage("picasso_owl.jpg","Picasso minimal owl")
|
#+CAPTION: Picasso minimal owl
|
||||||
|
[[./picasso_owl.jpg]]
|
||||||
|
|
||||||
Before continuing you need to be warned about some essential properties
|
Before continuing you need to be warned about some essential properties
|
||||||
of Haskell.
|
of Haskell.
|
||||||
|
@ -521,7 +511,8 @@ really watch this great (and funny) video:
|
||||||
:CUSTOM_ID: essential-haskell
|
:CUSTOM_ID: essential-haskell
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
blogimage("kandinsky_gugg.jpg","Kandinsky Gugg")
|
#+CAPTION: Kandinsky Gugg
|
||||||
|
[[./kandinsky_gugg.jpg]]
|
||||||
|
|
||||||
I suggest that you skim this part. Think of it as a reference. Haskell
|
I suggest that you skim this part. Think of it as a reference. Haskell
|
||||||
has a lot of features. A lot of information is missing here. Come back
|
has a lot of features. A lot of information is missing here. Come back
|
||||||
|
@ -769,7 +760,8 @@ The hard part can now begin.
|
||||||
:CUSTOM_ID: functional-style
|
:CUSTOM_ID: functional-style
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
blogimage("hr_giger_biomechanicallandscape_500.jpg","Biomechanical Landscape by H.R. Giger")
|
#+CAPTION: Biomechanical Landscape by H.R. Giger
|
||||||
|
[[./hr_giger_biomechanicallandscape_500.jpg]]
|
||||||
|
|
||||||
In this section, I will give a short example of the impressive
|
In this section, I will give a short example of the impressive
|
||||||
refactoring ability provided by Haskell. We will select a problem and
|
refactoring ability provided by Haskell. We will select a problem and
|
||||||
|
@ -1056,7 +1048,8 @@ We use this method to remove the =l=:
|
||||||
:CUSTOM_ID: higher-order-functions
|
:CUSTOM_ID: higher-order-functions
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
blogimage("escher_polygon.png","Escher")
|
#+CAPTION: Escher
|
||||||
|
[[./escher_polygon.png]]
|
||||||
|
|
||||||
To make things even better we should use higher order functions. What
|
To make things even better we should use higher order functions. What
|
||||||
are these beasts? Higher order functions are functions taking functions
|
are these beasts? Higher order functions are functions taking functions
|
||||||
|
@ -1286,7 +1279,8 @@ another essential aspect of Haskell: /Types/.
|
||||||
:CUSTOM_ID: types
|
:CUSTOM_ID: types
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
blogimage("salvador-dali-the-madonna-of-port-lligat.jpg","Dali, the madonna of port Lligat")
|
#+CAPTION: Dali, the madonna of port Lligat
|
||||||
|
[[./salvador-dali-the-madonna-of-port-lligat.jpg]]
|
||||||
|
|
||||||
#+BEGIN_QUOTE
|
#+BEGIN_QUOTE
|
||||||
%tldr
|
%tldr
|
||||||
|
@ -1405,6 +1399,9 @@ errors are caught before run time. Generally, in Haskell:
|
||||||
-----
|
-----
|
||||||
|
|
||||||
*** Type construction
|
*** Type construction
|
||||||
|
:PROPERTIES:
|
||||||
|
:CUSTOM_ID: type-construction
|
||||||
|
:END:
|
||||||
|
|
||||||
You can construct your own types. First, you can use aliases or type
|
You can construct your own types. First, you can use aliases or type
|
||||||
synonyms.
|
synonyms.
|
||||||
|
@ -1565,7 +1562,8 @@ This prints:
|
||||||
:CUSTOM_ID: trees
|
:CUSTOM_ID: trees
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
blogimage("magritte-l-arbre.jpg","Magritte, l'Arbre")
|
#+CAPTION: Magritte, l'Arbre
|
||||||
|
[[./magritte-l-arbre.jpg]]
|
||||||
|
|
||||||
We'll just give another standard example: binary trees.
|
We'll just give another standard example: binary trees.
|
||||||
|
|
||||||
|
@ -1761,7 +1759,8 @@ Binary tree of Char binary trees:
|
||||||
This is why I chose to prefix each line of tree display by =:= (except
|
This is why I chose to prefix each line of tree display by =:= (except
|
||||||
for the root).
|
for the root).
|
||||||
|
|
||||||
blogimage("yo_dawg_tree.jpg","Yo Dawg Tree")
|
#+CAPTION: Yo Dawg Tree
|
||||||
|
[[./yo_dawg_tree.jpg]]
|
||||||
|
|
||||||
#+BEGIN_SRC haskell
|
#+BEGIN_SRC haskell
|
||||||
putStrLn "\nTree of Binary trees of Char binary trees:"
|
putStrLn "\nTree of Binary trees of Char binary trees:"
|
||||||
|
@ -1826,7 +1825,8 @@ a tree containing a tree of trees!
|
||||||
:CUSTOM_ID: infinite-structures
|
:CUSTOM_ID: infinite-structures
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
blogimage("escher_infinite_lizards.jpg","Escher")
|
#+CAPTION: Escher
|
||||||
|
[[./escher_infinite_lizards.jpg]]
|
||||||
|
|
||||||
It is often said that Haskell is /lazy/.
|
It is often said that Haskell is /lazy/.
|
||||||
|
|
||||||
|
@ -2064,7 +2064,8 @@ rewarding.
|
||||||
:CUSTOM_ID: deal-with-io
|
:CUSTOM_ID: deal-with-io
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
blogimage("magritte_carte_blanche.jpg","Magritte, Carte blanche")
|
#+CAPTION: Magritte, Carte blanche
|
||||||
|
[[./magritte_carte_blanche.jpg]]
|
||||||
|
|
||||||
#+BEGIN_QUOTE
|
#+BEGIN_QUOTE
|
||||||
%tldr
|
%tldr
|
||||||
|
@ -2331,7 +2332,8 @@ If you practice a bit, you should be able to /use/ =IO=.
|
||||||
:CUSTOM_ID: io-trick-explained
|
:CUSTOM_ID: io-trick-explained
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
blogimage("magritte_pipe.jpg","Magritte, ceci n'est pas une pipe")
|
#+CAPTION: Magritte, ceci n'est pas une pipe
|
||||||
|
[[./magritte_pipe.jpg]]
|
||||||
|
|
||||||
#+BEGIN_QUOTE
|
#+BEGIN_QUOTE
|
||||||
Here is a %tldr for this section.
|
Here is a %tldr for this section.
|
||||||
|
@ -2553,20 +2555,21 @@ With, of course: =actionN w :: (World) -> (a,World)=.
|
||||||
#+BEGIN_QUOTE
|
#+BEGIN_QUOTE
|
||||||
IMPORTANT: there are only two important patterns to consider:
|
IMPORTANT: there are only two important patterns to consider:
|
||||||
|
|
||||||
#+BEGIN_EXAMPLE
|
#+BEGIN_SRC haskell
|
||||||
let (x,w1) = action1 w0 in
|
let (x,w1) = action1 w0 in
|
||||||
let (y,w2) = action2 x w1 in
|
let (y,w2) = action2 x w1 in
|
||||||
#+END_EXAMPLE
|
#+END_SRC
|
||||||
|
|
||||||
and
|
and
|
||||||
|
|
||||||
#+BEGIN_EXAMPLE
|
#+BEGIN_SRC haskell
|
||||||
let (_,w1) = action1 w0 in
|
let (_,w1) = action1 w0 in
|
||||||
let (y,w2) = action2 w1 in
|
let (y,w2) = action2 w1 in
|
||||||
#+END_EXAMPLE
|
#+END_SRC
|
||||||
#+END_QUOTE
|
#+END_QUOTE
|
||||||
|
|
||||||
leftblogimage("jocker_pencil_trick.jpg","Jocker pencil trick")
|
#+CAPTION: Jocker pencil trick
|
||||||
|
[[./jocker_pencil_trick.jpg]]
|
||||||
|
|
||||||
Now, we will do a magic trick. We will make the temporary world symbols
|
Now, we will do a magic trick. We will make the temporary world symbols
|
||||||
"disappear". We will =bind= the two lines. Let's define the =bind=
|
"disappear". We will =bind= the two lines. Let's define the =bind=
|
||||||
|
@ -2805,12 +2808,13 @@ Imagine what it would look like without the =(>>)= and =(>>=)=.
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
#+begin_comment
|
#+begin_comment
|
||||||
blogimage("dali_reve.jpg","Dali, reve. It represents a weapon out of the
|
#+CAPTION: Dali, reve. It represents a weapon out of the
|
||||||
mouth of a tiger, itself out of the mouth of another tiger, itself out
|
mouth of a tiger, itself out of the mouth of another tiger, itself out
|
||||||
of the mouth of a fish itself out of a grenade. I could have choosen a
|
of the mouth of a fish itself out of a grenade. I could have choosen a
|
||||||
picture of the Human centipede as it is a very good representation of
|
picture of the Human centipede as it is a very good representation of
|
||||||
what a monad really is. But just to think about it, I find this
|
what a monad really is. But just to think about it, I find this
|
||||||
disgusting and that wasn't the purpose of this document.")
|
disgusting and that wasn't the purpose of this document.
|
||||||
|
[[./dali_reve.jpg]]
|
||||||
#+end_comment
|
#+end_comment
|
||||||
|
|
||||||
Now the secret can be revealed: =IO= is a /monad/. Being a monad means
|
Now the secret can be revealed: =IO= is a /monad/. Being a monad means
|
||||||
|
@ -3002,7 +3006,8 @@ lists.
|
||||||
:CUSTOM_ID: the-list-monad
|
:CUSTOM_ID: the-list-monad
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
blogimage("golconde.jpg","Golconde de Magritte")
|
#+CAPTION: Golconde de Magritte
|
||||||
|
[[./golconde.jpg]]
|
||||||
|
|
||||||
The list monad helps us to simulate non-deterministic computations. Here
|
The list monad helps us to simulate non-deterministic computations. Here
|
||||||
we go:
|
we go:
|
BIN
src/posts/0010-Haskell-Now/jocker_pencil_trick.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
src/posts/0010-Haskell-Now/kandinsky_gugg.jpg
Normal file
After Width: | Height: | Size: 53 KiB |
BIN
src/posts/0010-Haskell-Now/learn_haskell_mordor.jpg
Normal file
After Width: | Height: | Size: 156 B |
BIN
src/posts/0010-Haskell-Now/magritte-l-arbre.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
src/posts/0010-Haskell-Now/magritte_carte_blanche.jpg
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
src/posts/0010-Haskell-Now/magritte_pipe.jpg
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
src/posts/0010-Haskell-Now/magritte_pleasure_principle.jpg
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
src/posts/0010-Haskell-Now/munch_TheScream.jpg
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
src/posts/0010-Haskell-Now/picasso_owl.jpg
Normal file
After Width: | Height: | Size: 7.6 KiB |
After Width: | Height: | Size: 60 KiB |
BIN
src/posts/0010-Haskell-Now/yo_dawg_tree.jpg
Normal file
After Width: | Height: | Size: 68 KiB |