diff --git a/src/css/mk.css b/src/css/mk.css index a9c8db2..4f77700 100644 --- a/src/css/mk.css +++ b/src/css/mk.css @@ -233,14 +233,14 @@ figure, .figure { --b1: #989EA8; --b2: #E5E8ED; --b3: #F4F7FC; - --y: #A98D50; - --o: #aa6550; - --r: #b85a64; + --y: #A98D50; + --o: #aa6550; + --r: #b85a64; --m: #af53b0; - --violet: #846f93; - --b: #5679a4; - --cyan: #4c8493; - --g: #728b5c; + --v: #846f93; + --b: #5679a4; + --c: #4c8493; + --g: #728b5c; /* Solaryzed accented colors */ --bg: var(--b03); @@ -438,7 +438,7 @@ blockquote:after, .main blockquote:after { } .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); } @@ -453,11 +453,11 @@ blockquote:after, .main blockquote:after { .org-rainbow-delimiters-depth-5, .org-diff-removed, .TODO { color:var(--r); } -.org-rainbow-delimiters-depth-6 { +.org-rainbow-delimiters-depth-6, .org-haskell-constructor { color:var(--o); } .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); } .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); } -.org-highlight-number-number { +.org-highlight-numbers-number, .org-highlight-number-number + { color:var(--rfg); } diff --git a/src/posts/0010-Haskell-Now/Haskell-logo.png b/src/posts/0010-Haskell-Now/Haskell-logo.png new file mode 100644 index 0000000..d36b129 Binary files /dev/null and b/src/posts/0010-Haskell-Now/Haskell-logo.png differ diff --git a/src/posts/0010-Haskell-Now/dali_reve.jpg b/src/posts/0010-Haskell-Now/dali_reve.jpg new file mode 100644 index 0000000..99e53b3 Binary files /dev/null and b/src/posts/0010-Haskell-Now/dali_reve.jpg differ diff --git a/src/posts/0010-Haskell-Now/dangerous_book.png b/src/posts/0010-Haskell-Now/dangerous_book.png new file mode 100644 index 0000000..31abd49 Binary files /dev/null and b/src/posts/0010-Haskell-Now/dangerous_book.png differ diff --git a/src/posts/0010-Haskell-Now/escher_infinite_lizards.jpg b/src/posts/0010-Haskell-Now/escher_infinite_lizards.jpg new file mode 100644 index 0000000..5d91af6 Binary files /dev/null and b/src/posts/0010-Haskell-Now/escher_infinite_lizards.jpg differ diff --git a/src/posts/0010-Haskell-Now/escher_polygon.png b/src/posts/0010-Haskell-Now/escher_polygon.png new file mode 100644 index 0000000..9afa3e2 Binary files /dev/null and b/src/posts/0010-Haskell-Now/escher_polygon.png differ diff --git a/src/posts/0010-Haskell-Now/golconde.jpg b/src/posts/0010-Haskell-Now/golconde.jpg new file mode 100644 index 0000000..e1941fb Binary files /dev/null and b/src/posts/0010-Haskell-Now/golconde.jpg differ diff --git a/src/posts/0010-Haskell-Now/hr_giger_biomechanicallandscape_500.jpg b/src/posts/0010-Haskell-Now/hr_giger_biomechanicallandscape_500.jpg new file mode 100644 index 0000000..c3103ea Binary files /dev/null and b/src/posts/0010-Haskell-Now/hr_giger_biomechanicallandscape_500.jpg differ diff --git a/src/posts/Haskell-the-Hard-Way.org b/src/posts/0010-Haskell-Now/index.org similarity index 96% rename from src/posts/Haskell-the-Hard-Way.org rename to src/posts/0010-Haskell-Now/index.org index f9b6d05..9fd5345 100644 --- a/src/posts/Haskell-the-Hard-Way.org +++ b/src/posts/0010-Haskell-Now/index.org @@ -1,33 +1,29 @@ #+title: Learn Haskell Fast and Hard #+subtitle: Blow your mind with Haskell -#+date: [2012-02-08] +#+date: [2019-12-15 Sun] #+author: Yann Esposito #+EMAIL: yann@esposito.host #+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 #+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 -Thanks to: +#+begin_quote +*Prelude* -- [[https://plus.google.com/u/0/113751420744109290534][Oleg Taykalo]] - you can find a Russian translation here: - [[http://habrahabr.ru/post/152889/][Part 1]] /&/ - [[http://habrahabr.ru/post/153383/][Part 2]], -- [[http://silly-bytes.blogspot.fr][Daniel Campoverde]] for the Spanish - translation here: - [[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. +In 2012, I really believed that every developer should learn Haskell. +It is the end of 2019 and I still believe it. +I don't think everyone needs to be a super Haskell ninja, but they should +at least discover what Haskell has to offer. +Learning Haskell opens your mind. +#+end_quote Mainstream languages share the same foundations: @@ -36,27 +32,32 @@ Mainstream languages share the same foundations: - pointers[fn:1] - data structures, objects and classes (for most) -Haskell is very different. The language uses a lot of concepts I had -never heard about before. Many of those concepts will help you become a -better programmer. +Haskell is very different. +The language uses a lot of concepts I had never heard about before. +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 -to provide what I lacked during my learning. +But learning Haskell can be hard. +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 -is no shortcut to learning Haskell. It is hard and challenging. But I -believe this is a good thing. It is because it is hard that Haskell is -interesting. +This article will certainly be hard to follow. +This is on purpose. +There is no shortcut to learning Haskell. +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 -[[http://learnyouahaskell.com]["Learn You a Haskell"]] and just after -[[http://www.realworldhaskell.org]["Real World Haskell"]]. I also -believe this is the right way to go. But to learn what Haskell is all -about, you'll have to read them in detail. +Today, I could not really provide a conventional path to learn Haskell. +So I think the best I can do is point you to the [[https://www.haskell.org/documentation/][haskell.org]] documentation +website. +And you will see that most path involve a quite long learning process. +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 -major aspects of Haskell. I also added some information I lacked while I -learned Haskell. +major aspects of Haskell. +I also added some information I lacked while I learned Haskell. The article contains five parts: @@ -80,20 +81,6 @@ The article contains five parts: - More on infinite tree; a more math oriented discussion about 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 :PROPERTIES: :CUSTOM_ID: introduction @@ -104,7 +91,8 @@ The article contains five parts: :CUSTOM_ID: install :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 [[https://haskellstack.org][=stack=]]. @@ -124,7 +112,8 @@ Tools: :CUSTOM_ID: don't-be-afraid :END: -blogimage("munch_TheScream.jpg","The Scream") +#+CAPTION: The Scream +[[./munch_TheScream.jpg]] Many books/articles about Haskell start by introducing some esoteric formula (quick sort, Fibonacci, etc...). I will do the exact opposite. @@ -217,7 +206,8 @@ languages. :CUSTOM_ID: very-basic-haskell :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 of Haskell. @@ -521,7 +511,8 @@ really watch this great (and funny) video: :CUSTOM_ID: essential-haskell :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 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 :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 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 :END: -blogimage("escher_polygon.png","Escher") +#+CAPTION: Escher +[[./escher_polygon.png]] To make things even better we should use higher order functions. What are these beasts? Higher order functions are functions taking functions @@ -1286,7 +1279,8 @@ another essential aspect of Haskell: /Types/. :CUSTOM_ID: types :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 %tldr @@ -1405,6 +1399,9 @@ errors are caught before run time. Generally, in Haskell: ----- *** Type construction +:PROPERTIES: +:CUSTOM_ID: type-construction +:END: You can construct your own types. First, you can use aliases or type synonyms. @@ -1565,7 +1562,8 @@ This prints: :CUSTOM_ID: trees :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. @@ -1761,7 +1759,8 @@ Binary tree of Char binary trees: This is why I chose to prefix each line of tree display by =:= (except for the root). -blogimage("yo_dawg_tree.jpg","Yo Dawg Tree") +#+CAPTION: Yo Dawg Tree +[[./yo_dawg_tree.jpg]] #+BEGIN_SRC haskell putStrLn "\nTree of Binary trees of Char binary trees:" @@ -1826,7 +1825,8 @@ a tree containing a tree of trees! :CUSTOM_ID: infinite-structures :END: -blogimage("escher_infinite_lizards.jpg","Escher") +#+CAPTION: Escher +[[./escher_infinite_lizards.jpg]] It is often said that Haskell is /lazy/. @@ -2064,7 +2064,8 @@ rewarding. :CUSTOM_ID: deal-with-io :END: -blogimage("magritte_carte_blanche.jpg","Magritte, Carte blanche") +#+CAPTION: Magritte, Carte blanche +[[./magritte_carte_blanche.jpg]] #+BEGIN_QUOTE %tldr @@ -2331,7 +2332,8 @@ If you practice a bit, you should be able to /use/ =IO=. :CUSTOM_ID: io-trick-explained :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 Here is a %tldr for this section. @@ -2553,20 +2555,21 @@ With, of course: =actionN w :: (World) -> (a,World)=. #+BEGIN_QUOTE IMPORTANT: there are only two important patterns to consider: - #+BEGIN_EXAMPLE - let (x,w1) = action1 w0 in - let (y,w2) = action2 x w1 in - #+END_EXAMPLE + #+BEGIN_SRC haskell + let (x,w1) = action1 w0 in + let (y,w2) = action2 x w1 in + #+END_SRC and - #+BEGIN_EXAMPLE - let (_,w1) = action1 w0 in - let (y,w2) = action2 w1 in - #+END_EXAMPLE + #+BEGIN_SRC haskell + let (_,w1) = action1 w0 in + let (y,w2) = action2 w1 in + #+END_SRC #+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 "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: #+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 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 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 Now the secret can be revealed: =IO= is a /monad/. Being a monad means @@ -3002,7 +3006,8 @@ lists. :CUSTOM_ID: the-list-monad :END: -blogimage("golconde.jpg","Golconde de Magritte") +#+CAPTION: Golconde de Magritte +[[./golconde.jpg]] The list monad helps us to simulate non-deterministic computations. Here we go: diff --git a/src/posts/0010-Haskell-Now/jocker_pencil_trick.jpg b/src/posts/0010-Haskell-Now/jocker_pencil_trick.jpg new file mode 100644 index 0000000..40d01a1 Binary files /dev/null and b/src/posts/0010-Haskell-Now/jocker_pencil_trick.jpg differ diff --git a/src/posts/0010-Haskell-Now/kandinsky_gugg.jpg b/src/posts/0010-Haskell-Now/kandinsky_gugg.jpg new file mode 100644 index 0000000..7091a36 Binary files /dev/null and b/src/posts/0010-Haskell-Now/kandinsky_gugg.jpg differ diff --git a/src/posts/0010-Haskell-Now/learn_haskell_mordor.jpg b/src/posts/0010-Haskell-Now/learn_haskell_mordor.jpg new file mode 100644 index 0000000..aff9f6c Binary files /dev/null and b/src/posts/0010-Haskell-Now/learn_haskell_mordor.jpg differ diff --git a/src/posts/0010-Haskell-Now/magritte-l-arbre.jpg b/src/posts/0010-Haskell-Now/magritte-l-arbre.jpg new file mode 100644 index 0000000..f989036 Binary files /dev/null and b/src/posts/0010-Haskell-Now/magritte-l-arbre.jpg differ diff --git a/src/posts/0010-Haskell-Now/magritte_carte_blanche.jpg b/src/posts/0010-Haskell-Now/magritte_carte_blanche.jpg new file mode 100644 index 0000000..b846615 Binary files /dev/null and b/src/posts/0010-Haskell-Now/magritte_carte_blanche.jpg differ diff --git a/src/posts/0010-Haskell-Now/magritte_pipe.jpg b/src/posts/0010-Haskell-Now/magritte_pipe.jpg new file mode 100644 index 0000000..56c0d7b Binary files /dev/null and b/src/posts/0010-Haskell-Now/magritte_pipe.jpg differ diff --git a/src/posts/0010-Haskell-Now/magritte_pleasure_principle.jpg b/src/posts/0010-Haskell-Now/magritte_pleasure_principle.jpg new file mode 100644 index 0000000..19b03f9 Binary files /dev/null and b/src/posts/0010-Haskell-Now/magritte_pleasure_principle.jpg differ diff --git a/src/posts/0010-Haskell-Now/munch_TheScream.jpg b/src/posts/0010-Haskell-Now/munch_TheScream.jpg new file mode 100644 index 0000000..73d1f6a Binary files /dev/null and b/src/posts/0010-Haskell-Now/munch_TheScream.jpg differ diff --git a/src/posts/0010-Haskell-Now/picasso_owl.jpg b/src/posts/0010-Haskell-Now/picasso_owl.jpg new file mode 100644 index 0000000..b4dfcb2 Binary files /dev/null and b/src/posts/0010-Haskell-Now/picasso_owl.jpg differ diff --git a/src/posts/0010-Haskell-Now/salvador-dali-the-madonna-of-port-lligat.jpg b/src/posts/0010-Haskell-Now/salvador-dali-the-madonna-of-port-lligat.jpg new file mode 100644 index 0000000..7e47cad Binary files /dev/null and b/src/posts/0010-Haskell-Now/salvador-dali-the-madonna-of-port-lligat.jpg differ diff --git a/src/posts/0010-Haskell-Now/yo_dawg_tree.jpg b/src/posts/0010-Haskell-Now/yo_dawg_tree.jpg new file mode 100644 index 0000000..7c041c9 Binary files /dev/null and b/src/posts/0010-Haskell-Now/yo_dawg_tree.jpg differ