git.iko.soy/Haskell-HSE/haskell-lectures-2024
on main help sign in
+ lecture 1
commitb71ac8e20a929bdc47096e4c7ff9f324e7edf1ad authorTurtlePU <sokolov.p64@gmail.com> dateTue 6 Feb 2024, 18:10 (3 years ago) parentc2a5a09
1 file changed+795
1.Intro.lhs+795
1.Intro.lhsnew file+795
@@ -0,0 +1,795 @@
1+Haskell 2024 - Intro
2+====================
3+
4+What is Haskell?
5+----------------
6+
7+As written in Wikipedia:
8+
9+Haskell (/ˈhæskəl/) is a general-purpose, statically-typed, purely functional
10+programming language with type inference and lazy evaluation. Designed for
11+teaching, research, and industrial applications, Haskell has pioneered a number
12+of programming language features such as type classes, which enable type-safe
13+operator overloading, and monadic input/output (IO). It is named after logician
14+Haskell Curry. Haskell's main implementation is the Glasgow Haskell Compiler
15+(GHC).
16+
17+Where is Haskell used?
18+----------------------
19+
20+Haskell is used in academia and in industry:
21+
22+* The proof assistant Agda is written in Haskell.
23+* Darcs is a revision control system written in Haskell, with several innovative
24+ features, such as more precise control of patches to apply.
25+* GHC is also often a testbed for advanced functional programming features and
26+ optimizations in other programming languages.
27+* Git-annex is a tool to manage (big) data files under Git version control. It
28+ also provides a distributed file synchronization system (git-annex assistant).
29+* Linspire Linux chose Haskell for system tools development.
30+* Pandoc is a tool to convert one markup format into another.
31+* Pugs is a compiler and interpreter for the Raku programming language (formerly
32+ Perl 6).
33+* TidalCycles is a domain special language for live coding musical patterns,
34+ embedded in Haskell.
35+* Xmonad is a window manager for the X Window System, written fully in Haskell.
36+* GarganText is a collaborative tool to map through semantic analysis texts on
37+ any web browser, written fully in Haskell and PureScript, which is used for
38+ instance in the research community to draw up state-of-the-art reports and
39+ roadmaps.
40+
41+Industry
42+~~~~~~~~
43+
44+* Bluespec SystemVerilog (BSV) is a language for semiconductor design that is an
45+ extension of Haskell. Also, Bluespec, Inc.'s tools are implemented in Haskell.
46+ Note this is an example of a domain specific language embedded into Haskell.
47+* Cryptol, a language and toolchain for developing and verifying cryptography
48+ algorithms, is implemented in Haskell.
49+* Facebook implements its anti-spam programs in Haskell, maintaining the
50+ underlying data access library as open-source software.
51+* The Cardano blockchain platform is implemented in Haskell.
52+* GitHub implemented Semantic, an open-source library for analysis, diffing, and
53+ interpretation of untrusted source code, in Haskell.
54+* Standard Chartered's financial modelling language Mu is syntactic Haskell
55+ running on a strict runtime.
56+* seL4, the first formally verified microkernel, used Haskell as a prototyping
57+ language for the OS developer. At the same time, the Haskell code defined an
58+ executable specification with which to reason, for automatic translation by
59+ the theorem-proving tool. The Haskell code thus served as an intermediate
60+ prototype before final C refinement.
61+* Target stores' supply chain optimization software is written in Haskell.
62+* Co–Star
63+
64+Some more examples from Serokell
65+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
66+
67+* Hasura is an open-source GraphQL engine that gives you instant access to a
68+ GraphQL API for your data. In the GitHub repository of Hasura, Haskell is the
69+ most used language, followed by languages like TypeScript, JavaScript, Python,
70+ and Go. At the start of 2022, Hasura raised $100 million.
71+* Microsoft uses Haskell in Bond, a cross-platform framework for working with
72+ schematized data. The Haskell part of Bond is mainly gbc, a command-line code
73+ generation tool that can generate C++ and C# code using Bond. For a long time,
74+ Microsoft Research also significantly supported the Glasgow Haskell Compiler
75+ (GHC) by employing Simon Peyton Jones to work on it.
76+* Tesla has been regularly hiring Haskell engineers and interns for some years
77+ already. There isn’t a lot of information out there about the exact specifics
78+ of their work. According to a comment in a job post made on Reddit, they use
79+ Haskell to generate C code that is then compiled into vehicle firmware.
80+* Freckle is an online learning platform that adjusts to the skills of students.
81+ They use Haskell for all of their backend services and most of their tooling.
82+* Galois is a company that specializes in the research and development of
83+ trustworthy software systems for fields where failure is unacceptable. One of
84+ their most interesting projects is Copilot, a stream-based DSL for writing and
85+ monitoring embedded C programs.
86+* Serokell uses Haskell to great success for most of their day-to-day software
87+ development projects. They have used it to build the settlement layer of the
88+ Cardano blockchain, programming languages for the Tezos blockchain,
89+ cryptocurrency exchanges, a multi-currency wallet with its own DSL, and more.
90+
91+What are the benefits of using Haskell?
92+---------------------------------------
93+
94+Companies above list three things as the most significant benefits of Haskell:
95+
96+1. Expressive type system.
97+2. Strong correctness guarantees.
98+3. Easy refactoring.
99+
100+In addition, while Haskell is a great programming language for everyday
101+purposes, we can separate two popular use cases:
102+
103+1. Complex systems where strong guarantees are required (such as blockchains
104+ like Cardano and fintech projects like Klarna).
105+2. The second is compilers and DSLs. On our list, the examples for this use case
106+ are projects like Bond, Semantic, Copilot.
107+
108+Both of these use cases heavily benefit from the strengths of Haskell and manage
109+to dodge most of its cons. They can rightfully be called the “killer apps” of
110+Haskell.
111+
112+If you are considering a project in these two areas, it’s hard to go wrong with
113+picking Haskell.
114+
115+Basic language constructs
116+=========================
117+
118+This file is actually a _literate Haskell_ file with extension `.lhs` where
119+every piece of code is indented with `>` like this:
120+
121+> a = 5
122+
123+Normal code is written without indent and is split into _modules_ each in their
124+own file with extension `.hs`. To write a comment, a double dash is used:
125+
126+> -- This is a comment inside code block in a literate Haskell file.
127+> {- And this is a multiline comment.
128+> A little useless, isn't it? -}
129+
130+Primitive Datatypes and Operators
131+---------------------------------
132+
133+Of course, Haskell has numbers, booleans, characters, strings and whatnot:
134+
135+> b = a + 1 -- 6
136+> c = 3 - 2 -- 1
137+> d = 10 * 2 -- 20
138+> e = 35 / 5
139+
140+However, if you load this file into a Haskell interpreter called `ghci`, you'll
141+see the following:
142+
143+```
144+$ ghci 1.Intro.lhs
145+GHCi, version 9.4.8: https://www.haskell.org/ghc/ :? for help
146+[1 of 2] Compiling Main ( 1.Intro.lhs, interpreted )
147+Ok, one module loaded.
148+ghci> e
149+7.0
150+```
151+
152+So division is not integer division by default. Actual integer division:
153+
154+> this_is_eight = 35 `div` 4
155+
156+Boolean operations:
157+
158+> f = not True
159+> g = not False
160+> h = True && False
161+> i = True || False
162+> j = 1 == 1
163+> k = 1 /= 1
164+> l = 1 < 10
165+
166+In the above examples, `not` is a function that takes one value. Haskell doesn't
167+need parentheses for function calls --- all the arguments are just listed after
168+the function. So the general pattern is: `func arg1 arg2 arg3...` See the
169+section on functions for information on how to write your own.
170+
171+Strings and characters:
172+
173+> m = "This is a string."
174+> n = 'a'
175+> -- o = 'You cant use single quotes for strings.' -- error!
176+
177+Strings can be concatenated:
178+
179+> p = "Hello " ++ "world!"
180+
181+A string is a list of characters:
182+
183+> q = ['H', 'e', 'l', 'l', 'o']
184+
185+Lists can be indexed with the `!!` operator followed by an index
186+
187+> s = "This is a string" !! 0
188+
189+Lists
190+-----
191+
192+Every element in a list must have the same type. These two lists are equal:
193+
194+> l1 = [1, 2, 3, 4, 5]
195+> l2 = [1..5]
196+
197+Ranges are versatile.
198+
199+> charRange = ['A'..'F'] -- "ABCDEF"
200+> orderingRange = [LT .. GT] -- [LT, EQ, GT]
201+
202+You can create a step in a range.
203+
204+> evenStep = [0,2..10] -- [0, 2, 4, 6, 8, 10]
205+> notStepped = [5..1] -- [] (Haskell defaults to incrementing)
206+> decrementStep = [5,4..1] -- [5, 4, 3, 2, 1]
207+
208+Indexing into a list
209+
210+> thirdGlyph = [1..10] !! 3 -- 4 (zero-based indexing)
211+
212+You can also have infinite lists in Haskell!
213+
214+> nats = [1..] -- a list of all the natural numbers
215+
216+Infinite lists work because Haskell has "lazy evaluation". This means that
217+Haskell only evaluates things when it needs to. So you can ask for the 1000th
218+element of your list and Haskell will give it to you:
219+
220+> someNat = [1..] !! 999 -- 1000
221+
222+And now Haskell has evaluated elements 1 - 1000 of this list...but the rest of
223+the elements of this "infinite" list don't exist yet! Haskell won't actually
224+evaluate them until it needs to.
225+
226+Joining two lists:
227+
228+> joinedLists = [1..5] ++ [6..10]
229+
230+Adding to the head of a list:
231+
232+> headCat = 0:[1..5] -- [0, 1, 2, 3, 4, 5]
233+
234+More list operations
235+
236+> someHead = head [1..5] -- 1
237+> someTail = tail [1..5] -- [2, 3, 4, 5]
238+> someInit = init [1..5] -- [1, 2, 3, 4]
239+> someLast = last [1..5] -- 5
240+
241+Actually, you can lookup them on [hoogle](https://hoogle.haskell.org/) or, even
242+better, find them there by their type signature!
243+
244+List comprehensions
245+
246+> comp = [x*2 | x <- [1..5]] -- [2, 4, 6, 8, 10]
247+
248+With a conditional
249+
250+> compCond = [x*2 | x <- [1..5], x*2 > 4] -- [6, 8, 10]
251+
252+With several iteratees
253+
254+> twoD = take 10 [x ^ 2 * y | x <- [1..], even x, x `mod` 3 == 0, y <- [1, -1]]
255+
256+Tuples
257+------
258+
259+Every element in a tuple can be a different type, but a tuple has a fixed
260+length. A tuple:
261+
262+> tupleExample = ("haskell", 1)
263+
264+Accessing elements of a pair (i.e. a tuple of length 2)
265+
266+> someFst = fst ("haskell", 1) -- "haskell"
267+> someSnd = snd ("haskell", 1) -- 1
268+
269+Pair element accessing does not work on n-tuples (i.e. triple, quadruple, etc)
270+
271+> -- snd ("snd", "can't touch this", "da na na na") -- error! see function below
272+
273+Functions
274+---------
275+
276+A simple function that takes two variables
277+
278+> add a b = a + b
279+
280+Using the function
281+
282+> three = add 1 2 -- 3
283+
284+You can also put the function name between the two arguments with backticks:
285+
286+> alsoThree = 1 `add` 2 -- 3
287+
288+You can also define functions that have no letters! This lets you define your
289+own operators! Here's an operator that does integer division
290+
291+> (//) a b = a `div` b
292+> eight = 35 // 4 -- 8
293+
294+Guards
295+~~~~~~
296+
297+An easy way to do branching in functions
298+
299+> fib x
300+> | x < 2 = 1
301+> | otherwise = fib (x - 1) + fib (x - 2)
302+
303+Pattern matching
304+~~~~~~~~~~~~~~~~
305+
306+Pattern matching is similar. Here we have given three different equations that
307+define `fib'`. Haskell will automatically use the first equation whose left hand
308+side pattern matches the value.
309+
310+> fib' 1 = 1
311+> fib' 2 = 2
312+> fib' x = fib' (x - 1) + fib' (x - 2)
313+
314+Pattern matching on tuples
315+~~~~~~~~~~~~~~~~~~~~~~~~~~
316+
317+> sndOfTriple (_, y, _) = y -- use a wild card (_) to bypass naming unused value
318+
319+Pattern matching on lists
320+~~~~~~~~~~~~~~~~~~~~~~~~~
321+
322+Here `x` is the first element in the list, and `xs` is the rest of the list. We
323+can write our own map function:
324+
325+> myMap func [] = []
326+> myMap func (x:xs) = func x:(myMap func xs)
327+
328+Anonymous functions are created with a backslash followed by all the arguments.
329+
330+> mapped = myMap (\x -> x + 2) [1..5] -- [3, 4, 5, 6, 7]
331+
332+Using fold (called `inject` in some languages) with an anonymous function
333+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
334+
335+foldl1 means fold left, and use the first value in the list as the initial value
336+for the accumulator.
337+
338+> usingFold = foldl1 (\acc x -> acc + x) [1..5] -- 15
339+
340+Partial application
341+~~~~~~~~~~~~~~~~~~~
342+
343+If you don't pass in all the arguments to a function, it gets "partially
344+applied". That means it returns a function that takes the rest of the arguments.
345+
346+> foo = add 10 -- foo is now a function that takes a number and adds 10 to it
347+> fifteen = foo 5 -- 15
348+
349+Another way to write the same thing. It is called a "section":
350+
351+> foo' = (10 +)
352+> alsoFifteen = foo' 5 -- 15
353+
354+Function composition
355+~~~~~~~~~~~~~~~~~~~~
356+
357+The operator `.` chains functions together. For example, here foo is a function
358+that takes a value. It adds 10 to it, multiplies the result of that by 4, and
359+then returns the final value.
360+
361+> foo'' = (4 *) . (10 +)
362+> sixty = foo'' 5 -- 4*(10+5) = 60
363+
364+Fixing precedence
365+~~~~~~~~~~~~~~~~~
366+
367+Haskell has an operator called `$`. This operator applies a function to a given
368+parameter. In contrast to standard function application, which has highest
369+possible priority of 10 and is left-associative, the `$` operator has priority
370+of 0 and is right-associative. Such a low priority means that the expression on
371+its right is applied as a parameter to the function on its left.
372+
373+Before:
374+
375+> evenSeven = even (fib 7) -- false
376+
377+Equivalently:
378+
379+> evenSeven' = even $ fib 7 -- false
380+
381+Composing functions:
382+
383+> evenSeven'' = even . fib $ 7 -- false
384+
385+Type signatures
386+---------------
387+
388+Haskell has a very strong type system, and every valid expression has a type.
389+Some basic types:
390+
391+> five = 5 :: Integer
392+> hello = "hello" :: String
393+> truth = True :: Bool
394+
395+Functions have types too. `not` takes a boolean and returns a boolean:
396+
397+> not' = not :: Bool -> Bool
398+
399+Here's a function that takes two arguments:
400+
401+> add' = add :: Integer -> Integer -> Integer
402+
403+When you define a value, it's good practice to write its type above it:
404+
405+> double :: Integer -> Integer
406+> double x = x * 2
407+
408+Typed holes
409+~~~~~~~~~~~
410+
411+Haskell's type system allows one to use "typed holes" -- you can replace an
412+expression with an underscore and a compiler would tell you what is the expected
413+type of a missing expression:
414+
415+> -- double' x = _ * 2 :: Integer
416+
417+Control Flow and If Expressions
418+-------------------------------
419+
420+if-expressions
421+
422+> haskell = if 1 == 1 then "awesome" else "awful" -- haskell = "awesome"
423+
424+if-expressions can be on multiple lines too, indentation is important
425+
426+> haskell' = if 1 == 1
427+> then "awesome"
428+> else "awful"
429+
430+Case expressions: Here's how you could parse command line arguments
431+
432+> parseArgs args =
433+> case args of
434+> "help" -> printHelp
435+> "start" -> startProgram
436+> _ -> putStrLn "bad args"
437+>
438+> printHelp = undefined -- see Hoogle to learn what this is
439+> startProgram = undefined
440+
441+Haskell doesn't have loops; it uses recursion instead. map applies a function
442+over every element in a list
443+
444+> someEvens = map (*2) [1..5] -- [2, 4, 6, 8, 10]
445+
446+You can make a for function using map
447+
448+> for array func = map func array
449+
450+And then use it
451+
452+> strings = for [0..5] $ \i -> show i
453+
454+We could've written that like this too:
455+
456+> strs = for [0..5] show
457+
458+You can use foldl or foldr to reduce a list: foldl <fn> <initial value> <list>
459+
460+> fortyThree = foldl (\x y -> 2*x + y) 4 [1,2,3] -- 43
461+
462+This is the same as (2 * (2 * (2 * 4 + 1) + 2) + 3)
463+
464+While foldl is left-handed, foldr is right-handed
465+
466+> sixteen = foldr (\x y -> 2*x + y) 4 [1,2,3] -- 16
467+
468+This is now the same as (2 * 1 + (2 * 2 + (2 * 3 + 4)))
469+
470+Data Types
471+----------
472+
473+A data type is declared with a 'type constructor' on the left and one or more
474+'data constructors' on the right, separated by the pipe | symbol. This is a
475+sum/union type. Each data constructor is a (possibly nullary) function that
476+creates an object of the type named by the type constructor.
477+
478+This is essentially an enum
479+
480+> data Color = Red | Blue | Green -- enum in Rust
481+
482+Now you can use it in a function:
483+
484+> say :: Color -> String
485+> say Red = "You are Red!"
486+> say Blue = "You are Blue!"
487+> say Green = "You are Green!"
488+
489+Note that the type constructor is used in the type signature and the data
490+constructors are used in the body of the function. Data constructors are
491+primarily pattern-matched against.
492+
493+This next one is a traditional container type holding two fields. In a type
494+declaration, data constructors take types as parameters. Data constructors can
495+have the same name as type constructors: this is common where the type only has
496+a single data constructor, although here we do not do this to reduce confusion
497+for newcomers.
498+
499+> data Point = Cartesian Float Float
500+
501+This can be used in a function like:
502+
503+> distance :: Point -> Point -> Float
504+> distance (Cartesian x y) (Cartesian x' y') = sqrt $ dx + dy
505+> where dx = (x - x') ** 2
506+> dy = (y - y') ** 2
507+
508+Types can have multiple data constructors with arguments, too
509+
510+> data Name = Mononym String
511+> | FirstLastName String String
512+> | FullName String String String
513+
514+To make things clearer, we can use record syntax
515+
516+> data PointRecord = CartesianPoint2D { x :: Float, y :: Float }
517+> | PolarPoint2D { r :: Float, theta :: Float }
518+
519+> myPoint = CartesianPoint2D { x = 7.0, y = 10.0 }
520+
521+Using record syntax automatically creates accessor functions:
522+
523+> xOfMyPoint = x myPoint -- 7.0
524+
525+Record syntax also allows a simple form of update
526+
527+> myPoint' = myPoint { x = 9.0 } -- CartesianPoint2D { x = 9.0, y = 10.0 }
528+
529+Even if a type is defined with record syntax, it can be declared like a simple
530+data constructor. This is fine:
531+
532+> myPoint'' = CartesianPoint2D 3.3 4.0
533+
534+It's also useful to pattern match data constructors in `case` expressions
535+
536+> distanceFromOrigin x =
537+> case x of (CartesianPoint2D x y) -> sqrt $ x ** 2 + y ** 2
538+> (PolarPoint2D r _) -> r
539+
540+Your data types can have type parameters too:
541+
542+```haskell
543+data Maybe a = Nothing | Just a
544+```
545+
546+These are all Maybes, but with different `a`s:
547+
548+> justHello = Just "hello" -- of type `Maybe String`
549+> justOne = Just 1 -- of type `Maybe Int`
550+> nothing = Nothing -- of type `Maybe a` for any `a`
551+
552+For convenience we can also create type synonyms with the 'type' keyword
553+
554+> type String' = [Char]
555+
556+Unlike `data` types, type synonyms need no constructor, and can be used anywhere
557+a synonymous data type could be used. Say we have the following type synonyms
558+and items with the following type signatures
559+
560+> -- For demonstration purposes, these types have no constructors
561+> data Person
562+> data Circle
563+>
564+> -- Types in which we are interested
565+> type Weight = Float
566+> type Height = Float
567+> type Point2D = (Float, Float)
568+>
569+> getMyHeightAndWeight :: Person -> (Height, Weight)
570+> getMyHeightAndWeight = undefined
571+>
572+> findCenter :: Circle -> Point2D
573+> findCenter = undefined
574+>
575+> somePerson :: Person
576+> somePerson = undefined
577+>
578+> someCircle :: Circle
579+> someCircle = undefined
580+>
581+> distance2D :: Point2D -> Point2D -> Float
582+> distance2D = undefined
583+
584+The following would compile and run without issue, even though it does not make
585+sense semantically, because the type synonyms reduce to the same base types:
586+
587+> nonsense = distance2D (getMyHeightAndWeight somePerson) (findCenter someCircle)
588+
589+Typeclasses
590+-----------
591+
592+Typeclasses are one way Haskell does polymorphism. They are similar to
593+interfaces in other languages: a typeclass defines a set of functions that must
594+work on any type that is in that typeclass.
595+
596+The
597+[Eq](https://hackage.haskell.org/package/base-4.19.0.0/docs/Prelude.html#t:Eq)
598+typeclass is for types whose instances can be tested for equality with one
599+another.
600+
601+```Haskell
602+class Eq a where
603+ (==) :: a -> a -> Bool
604+ (/=) :: a -> a -> Bool
605+ x == y = not (x /= y)
606+ x /= y = not (x == y)
607+```
608+
609+This defines a typeclass that requires two functions, (==) and (/=). It also
610+declares that one function can be declared in terms of another, so it is enough
611+that *either* the (==) function or the (/=) is defined and the other will be
612+'filled in' based on the typeclass definition.
613+
614+To make a type a member of a type class, the `instance` keyword is used
615+
616+> data TrafficLight = TLRed | TLYellow | TLGreen
617+>
618+> instance Eq TrafficLight where
619+> TLRed == TLRed = True
620+> TLGreen == TLGreen = True
621+> TLYellow == TLYellow = True
622+> _ == _ = False
623+
624+(Note that, while declaring `TrafficLight` constructors, we had to name
625+constructors differently in order for them to not clash with `Color`
626+constructors we defined earlier. It is common to either prefix constructor
627+names with type name abbreviation or define types in different modules
628+altogether)
629+
630+Now we can use `(==)` and `(/=)` with TrafficLight objects:
631+
632+> canProceedThrough :: TrafficLight -> Bool
633+> canProceedThrough t = t /= TLRed
634+
635+You can NOT create an instance definition for a type synonym, though.
636+
637+Functions can be written to take typeclasses with type parameters, rather than
638+types, assuming that the function only relies on features of the typeclass:
639+
640+> isEqual :: Eq a => a -> a -> Bool
641+> isEqual x y = x == y
642+
643+Note that x and y MUST be the same type, as they are both defined as being of
644+type parameter 'a'. A typeclass does not state that different types in the
645+typeclass can be mixed together. So `isEqual Red 2` is invalid even though 2 is
646+an Int which is an instance of Eq, and Red is a TrafficLight which is also an
647+instance of Eq.
648+
649+Other common typeclasses are:
650+
651+* `Ord` for types that can be ordered, allowing you to use >, <=, etc.
652+* `Read` for types that can be created from a string representation
653+* `Show` for types that can be converted to a string for display
654+* `Num`, `Real`, `Integral`, `Fractional` for types that can do math
655+* `Enum` for types that can be stepped through
656+* `Bounded` for types with a maximum and minimum
657+
658+Literals
659+~~~~~~~~
660+
661+We used character, string and list literals back from the very start. It is
662+simple to understand what they mean and how to use them. However, numeric
663+literals are not so simple. If we ask GHCi: "what is the type of 2?", we get:
664+
665+```
666+ghci> :t 2
667+2 :: Num a => a
668+```
669+
670+So numeric literals are actually polymorphic and do not have a concrete type.
671+Not that this is not the same as casts because the following is not allowed:
672+
673+> two = 2 :: Integer
674+> -- float = two * 0.5 -- would not pass the type check
675+
676+Deriving
677+~~~~~~~~
678+
679+Haskell can automatically make types part of Eq, Ord, Read, Show, Enum and
680+Bounded with the `deriving` keyword at the end of the type declaration
681+
682+> data PointDerives = Point Float Float deriving (Eq, Read, Show)
683+
684+In this case it is NOT necessary to create an 'instance' definition.
685+
686+Haskell IO
687+----------
688+
689+While IO can't be explained fully without explaining monads, it is not hard to
690+explain enough to get going.
691+
692+When a Haskell program is executed, `main` is called. It must return a value of
693+type `IO a` for some type `a`. For example:
694+
695+> main :: IO ()
696+> main = putStrLn $ "Hello, sky! " ++ (say Blue)
697+
698+(`putStrLn` has type `String -> IO ()`)
699+
700+It is easiest to do IO if you can implement your program as a function from
701+String to String. The function
702+
703+> interact' = interact :: (String -> String) -> IO ()
704+
705+Inputs some text, runs a function on it, and prints out the output.
706+
707+> countLines :: String -> String
708+> countLines = show . length . lines
709+
710+> main' = interact countLines
711+
712+You can think of a value of type `IO ()` as representing a sequence of actions
713+for the computer to do, much like a computer program written in an imperative
714+language. We can use the `do` notation to chain actions together. For example:
715+
716+> sayHello :: IO ()
717+> sayHello = do
718+> putStrLn "What is your name?"
719+> name <- getLine -- this gets a line and gives it the name "name"
720+> putStrLn $ "Hello, " ++ name
721+
722+Exercise: write your own version of `interact` that only reads one line of
723+input.
724+
725+The code in `sayHello` will never be executed, however. The only action that
726+ever gets executed in the source file is the value of `main`. To run `sayHello`,
727+comment out the above definition of `main`, replace it with `main = sayHello`
728+and run `runhaskell <file name>`.
729+
730+Let's understand better how the function `getLine` we just used works. Its type
731+is:
732+
733+> getLine' = getLine :: IO String
734+
735+You can think of a value of type `IO a` as representing a computer program that
736+will generate a value of type `a` when executed (in addition to anything else it
737+does). We can name and reuse this value using `<-`. We can also make our own
738+action of type `IO String`:
739+
740+> action :: IO String
741+> action = do
742+> putStrLn "This is a line. Duh"
743+> input1 <- getLine
744+> input2 <- getLine
745+> -- The type of the `do` statement is that of its last line.
746+> -- `return` is not a keyword, but merely a function
747+> return (input1 ++ "\n" ++ input2) -- return :: String -> IO String
748+
749+> action' = putStrLn "This is a line" >> (getLine >>= (\input1 ->
750+> getLine >>= (\input2 -> return (input1 ++ "\n" ++ input2))))
751+
752+We can use this just like we used `getLine`:
753+
754+> main'' = do
755+> putStrLn "I will echo two lines!"
756+> result <- action
757+> putStrLn result
758+> putStrLn "This was all, folks!"
759+
760+The type `IO` is an example of a "monad". The way Haskell uses a monad to do IO
761+allows it to be a purely functional language. Any function that interacts with
762+the outside world (i.e. does IO) gets marked as `IO` in its type signature. This
763+lets us reason about which functions are "pure" (don't interact with the outside
764+world or modify state) and which functions aren't.
765+
766+This is a powerful feature, because it's easy to run pure functions
767+concurrently; so, concurrency in Haskell is very easy.
768+
769+Monads
770+------
771+
772+Actually, `do`-notation has wider application than only constructing IO values.
773+Is is applicable for every _monad_:
774+
775+```
776+ghci> :i Monad
777+type Monad :: (* -> *) -> Constraint
778+class Applicative m => Monad m where
779+ (>>=) :: m a -> (a -> m b) -> m b
780+ (>>) :: m a -> m b -> m b
781+ return :: a -> m a
782+```
783+
784+In other words, `m` is a monad if it allows to construct "pure" values of type
785+`m a` from any value of type `a` and if it allows to sequence actions of type
786+`m a` and `m b` and yield a result of type `m b`, where the second action either
787+can (`(>>=)`) or cannot (`(>>)`) depend on the result of the first action.
788+
789+Sources & References
790+====================
791+
792+* [Wikipedia page on Haskell](https://en.wikipedia.org/wiki/Haskell)
793+* [Serokell blog post on Haskell in industry](https://serokell.io/blog/top-software-written-in-haskell)
794+* [Memo for basic Haskell constructions](https://learnxinyminutes.com/docs/haskell/)
795+* [Hoogle, Haskell code search](https://hoogle.haskell.org/)