├── .gitmodules ├── CheatSheet.org ├── CheatSheet.pdf ├── CheatSheet_Portrait.pdf ├── README.org └── _config.yml /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "CheatSheet"] 2 | path = CheatSheet 3 | url = https://github.com/alhassy/CheatSheet.git 4 | -------------------------------------------------------------------------------- /CheatSheet.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Haskell CheatSheet 2 | # +SUBTITLE: ---Reference Sheet for “What I'm Currently Learning”--- 3 | #+MACRO: blurb A reference sheet for the basics of the mind-expanding Haskell language (•̀ᴗ•́)و 4 | #+AUTHOR: [[https://alhassy.github.io/][Musa Al-hassy]] 5 | #+EMAIL: alhassy@gmail.com 6 | #+INCLUDE: CheatSheet/CheatSheetSetup.org 7 | #+PROPERTY: header-args :results none 8 | #+TODO: Todo | spacing LaTeX 9 | 10 | * LaTeX Extra, Local, Setup :ignore: 11 | 12 | #+MACRO: newline @@latex: \newline@@ 13 | 14 | # Empty by default. 15 | #+LATEX_HEADER: \def\cheatsheeturl{https://github.com/alhassy/HaskellCheatSheet} 16 | 17 | # The following are the defaults & may be omitted. 18 | #+LATEX_HEADER: \def\cheatsheetcols{2} 19 | #+LATEX_HEADER: \landscapetrue 20 | #+LATEX_HEADER: \def\cheatsheetitemsep{-0.5em} 21 | 22 | # Example unicode declarations; see section “unicode” below. 23 | #+LATEX_HEADER: \newunicodechar{𝑻}{\ensuremath{T}} 24 | #+LATEX_HEADER: \newunicodechar{⊕}{\ensuremath{\oplus}} 25 | #+LATEX_HEADER: \newunicodechar{≈}{\ensuremath{\approx}} 26 | #+LATEX_HEADER: \newunicodechar{𝓍}{\ensuremath{x}} 27 | #+LATEX_HEADER: \newunicodechar{α}{\ensuremath{\alpha}} 28 | #+LATEX_HEADER: \newunicodechar{β}{\ensuremath{\beta}} 29 | #+LATEX_HEADER: \newunicodechar{ε}{\ensuremath{\epsilon}} 30 | #+LATEX_HEADER: \newunicodechar{∂}{\ensuremath{\partial}} 31 | #+LATEX_HEADER: \newunicodechar{⊝}{\ensuremath{\ominus}} 32 | #+LATEX_HEADER: \newunicodechar{₋}{\ensuremath{_-}} 33 | #+LATEX_HEADER: \newunicodechar{⟶}{\ensuremath{\rightarrow}} 34 | #+LATEX_HEADER: \newunicodechar{∉}{\ensuremath{\not\in}} 35 | #+LATEX_HEADER: \newunicodechar{ }{\ensuremath{\;\;}} 36 | 37 | * COMMENT Contents :TOCish:QUOTE:ignore: 38 | #+BEGIN_QUOTE 39 | - [[#hello-home][Hello, Home!]] 40 | - [[#pattern-matching][Pattern Matching]] 41 | - [[#local-bindings][Local Bindings]] 42 | - [[#operators][Operators]] 43 | - [[#types][Types]] 44 | - [[#tuples][Tuples]] 45 | - [[#lists][Lists]] 46 | - [[#pattern-matching-on-lists][Pattern Matching on Lists]] 47 | - [[#common-methods-on-lists][Common Methods on Lists]] 48 | - [[#list-design-patterns][List ‘Design Patterns’]] 49 | - [[#map][Map]] 50 | - [[#filter][Filter]] 51 | - [[#fold][Fold]] 52 | - [[#algebraic-data-types][Algebraic data types]] 53 | - [[#typeclasses-and-overloading][Typeclasses and overloading]] 54 | - [[#functor][Functor]] 55 | - [[#identity-axiom][Identity Axiom]] 56 | - [[#fusion-axiom][Fusion Axiom]] 57 | - [[#functors-do-not-necessarily-contain-anything][Functors do not necessarily ‘contain’ anything]] 58 | - [[#misc-results-about-functors][Misc results about Functors]] 59 | - [[#functor-examples][Functor Examples]] 60 | - [[#applicative][Applicative]] 61 | - [[#axioms][Axioms]] 62 | - [[#canonical-form----liftn][Canonical Form -- =liftN=]] 63 | - [[#monoidal-presentation][Monoidal Presentation]] 64 | - [[#applicative-examples][Applicative Examples]] 65 | - [[#do-notation----subtle-difference-between-applicatives-and-monads][~Do~-Notation ---Subtle difference between applicatives and monads]] 66 | - [[#do-notation-with-tuples-and-functions][Do-notation with tuples and functions]] 67 | - [[#formal-definition-of-do-notation][Formal Definition of ~Do~-Notation]] 68 | - [[#monad-laws][Monad Laws]] 69 | - [[#monad-examples][Monad Examples]] 70 | - [[#running-example----a-simple-arithmetic-language][Running Example ---A Simple Arithmetic Language]] 71 | - [[#maybe----possibly-failing-computations][Maybe ---Possibly Failing Computations]] 72 | - [[#writer----logging-information-as-we-compute][Writer ---Logging Information as we Compute]] 73 | - [[#reader----accessing-global-read-only-data][Reader ---Accessing ‘Global, read-only, data’]] 74 | - [[#state----read-and-write-to-local-storage][State ---Read and write to local storage]] 75 | - [[#reads][Reads]] 76 | #+END_QUOTE 77 | 78 | * Hello, Home! 79 | 80 | #+BEGIN_SRC haskell :tangle home.hs 81 | main = do putStr "What's your name? " 82 | name <- getLine 83 | putStrLn ("It's 2020, " ++ name ++ "! Stay home, stay safe!") 84 | #+END_SRC 85 | 86 | * Pattern Matching 87 | 88 | Functions can be defined using the usual ~if_then_else_~ construct, or 89 | as expressions /guarded/ by Boolean expressions as in mathematics, or 90 | by /pattern matching/ ---a form of ‘syntactic comparision’. 91 | 92 | #+BEGIN_SRC haskell 93 | fact n = if n == 0 then 1 else n * fact (n - 1) 94 | 95 | fact' n | n == 0 = 1 96 | | n != 0 = n * fact' (n - 1) 97 | 98 | fact'' 0 = 1 99 | fact'' n = n * fact'' (n - 1) 100 | #+END_SRC 101 | 102 | The above definitions of the factorial function are all equal. 103 | 104 | Guards, as in the second version, are a form of ‘multi-branching conditional’. 105 | 106 | In the final version, when a call, say, ~fact 5~ happens we compare 107 | /syntactically/ whether ~5~ and the first pattern ~0~ are the same. They are not, 108 | so we consider the second case with the understanding that an identifier 109 | appearing in a pattern matches /any/ argument, so the second clause is used. 110 | 111 | Hence, when pattern matching is used, order of equations matters: If we 112 | declared the ~n~-pattern first, then the call ~fact 0~ would match it and we end 113 | up with ~0 * fact (-1)~, which is not what we want! 114 | 115 | If we simply defined the final ~fact~ using /only/ the first clause, then 116 | ~fact 1~ would crash with the error /Non-exhaustive patterns in function fact/. 117 | That is, we may define /partial functions/ by not considering all possible shapes of 118 | inputs. 119 | 120 | # Matches are tried in the order in which the equations are specfied, and the 121 | # first pattern that matches causes the corresponding equation to be selected. 122 | 123 | See also [[https://gitlab.haskell.org/ghc/ghc/-/wikis/view-patterns][“view patterns”]]. 124 | 125 | * Local Bindings 126 | 127 | An equation can be qualified by a ~where~ or ~let~ clause for defining values or 128 | functions used only within an expression. 129 | 130 | #+BEGIN_SRC haskell 131 | …e…e…e where e = ℯ𝓍𝓅𝓇 132 | ≈ let e = ℯ𝓍𝓅𝓇 in …ℯ𝓍𝓅𝓇…ℯ𝓍𝓅𝓇…ℯ𝓍𝓅𝓇 133 | #+END_SRC 134 | 135 | It sometimes happens in functional programs that one clause of a function needs 136 | /part of/ an argument, while another operators on the /whole/ argument. It it 137 | tedious (and inefficient) to write out the structure of the complete argument 138 | again when referring to it. 139 | Use the “as operator” ~@~ to label all or part of an argument, as in 140 | 141 | #+BEGIN_SRC haskell 142 | f label@(x:y:ys) = ⋯ 143 | #+END_SRC 144 | 145 | * Operators 146 | Infix operators in Haskell must consist entiry of ‘symbols’ such as ~&, ^, !, …~ 147 | rather than alphanumeric characters. Hence, while addition, ~+~, is written infix, 148 | integer division is written prefix with ~div~. 149 | 150 | We can always use whatever fixity we like: 151 | - If ~f~ is any /prefix/ binary function, then ~x `f` y~ is a valid /infix/ call. 152 | - If ~⊕~ is any /infix/ binary operator, then ~(⊕) x y~ is a valid /prefix/ call. 153 | 154 | It is common to fix one argument ahead of time, e.g., ~λ x → x + 1~ is the 155 | successor operation and is written more tersely as ~(+1)~. More generally, ~(⊕r) = 156 | λ x → x ⊕ r~. 157 | 158 | The usual arithmeic operations are ~+, /, *, -~ but ~%~ is used to make fractions. 159 | 160 | The Boolean operations are ~==, /=, &&, ||~ for equality, discrepancy, 161 | conjunction, and disjunction. 162 | 163 | * Types 164 | 165 | Type are inferred, but it is better to write them explicitly so that /you 166 | communicate your intentions to the machine/. If you /think/ that expression ~e~ has 167 | type ~τ~ then write ~e :: τ~ to /communicate/ that to the machine, which will silently 168 | accept your claim or reject it loudly. 169 | 170 | | Type | Name | Example Value | 171 | |--------------------+-----------+-------------------| 172 | | Small integers | ~Int~ | ~42~ | 173 | | Unlimited integers | ~Integer~ | ~7376541234~ | 174 | | Reals | ~Float~ | ~3.14~ and ~2 % 5~ | 175 | | Booleans | ~Boolean~ | ~True~ and ~False~ | 176 | | Characters | ~Char~ | ~'a'~ and ~'3'~ | 177 | | Strings | ~String~ | ~"salam"~ | 178 | | Lists | ~[α]~ | ~[]~ or ~[x₁, …, xₙ]~ | 179 | | Tuples | ~(α, β, γ)~ | ~(x₁, x₂, x₃)~ | 180 | | Functions | ~α → β~ | ~λ x → ⋯~ | 181 | 182 | /Polymorphism/ is the concept that allows one function to operate on different types. 183 | - A function whose type contains /variables/ is called a /polymorphic function/. 184 | - The simplest polymorphic function is ~id ∷ a -> a~, defined by ~id x = x~. 185 | 186 | * Tuples 187 | 188 | *Tuples* ~(α₁, …, αₙ)~ are types with values written ~(x₁, …, xₙ)~ {{{newline}}} where 189 | each ~xᵢ :: αᵢ~. The are a form of ‘record’ or ‘product’ type. 190 | 191 | E.g., ~(True, 3, 'a') :: (Boolean, Int, Char)~. 192 | 193 | Tuples are used to “return multiple values” from a function. 194 | 195 | Two useful functions on tuples of length 2 are: 196 | #+BEGIN_SRC haskell 197 | fst :: (α, β) → α 198 | fst (x, y) = x 199 | 200 | snd :: (α, β) → β 201 | snd (x, y) = β 202 | #+END_SRC 203 | 204 | If in addition you ~import Control.Arrow~ then you may use: 205 | #+BEGIN_SRC haskell 206 | first :: (α → τ) → (α, β) → (τ, β) 207 | first f (x, y) = (f x, y) 208 | 209 | second :: (β → τ) → (α, β) → (α, τ) 210 | second g (x, y) = (x, g y) 211 | 212 | (***) :: (α → α′) → (β → β) → (α, β) → (α′, β′) 213 | (f *** g) (x, y) = (f x, g y) 214 | 215 | (&&&) :: (τ → α) → (τ → β) → τ → (α, β) 216 | (f &&& g) x = (f x, g x) 217 | #+END_SRC 218 | 219 | * Lists 220 | 221 | *Lists* are sequences of items of the same type. 222 | {{{newline}}} 223 | If each ~xᵢ ∷ α~ then ~[x₁, …, xₙ] ∷ [α]~. 224 | 225 | Lists are useful for functions that want to ‘non-deterministicly’ return a 226 | value: {{{newline}}} They return a list of all possible values. 227 | 228 | - The /empty list/ is ~[]~ 229 | - We “cons”truct nonempty lists using ~(:) ∷ α → [α] → [α]~ 230 | - Abbreviation: ~[x₁, …, xₙ] = x₁ ∶ (x₂ ∶ (⋯ (xₙ ∶ [])))~ 231 | - /List comprehensions/: ~[f x | x <- xs, p x]~ is the list of elements 232 | ~f x~ where ~x~ is an element from list ~xs~ and ~x~ satisfies the property ~p~ 233 | * E.g., ~[2 * x | x <- [2, 3, 4], x < 4] ≈ [2 * 2, 2 * 3] ≈ [4, 6]~ 234 | # * /From ~xs~ we filter-out only those satisfying ~p~ then transform what's left with ~f~./ 235 | - Shorthand notation for segments: ~u~ may be ommitted to yield /infinite lists/ 236 | * ~[l .. u] = [l, l + 1, l + 2, …, u]~. 237 | # - This notation also works on characters. 238 | * ~[a, b, .., u] = [a + i * step | i <- [0 .. u - a] ] where step = b - a~ 239 | 240 | *Strings* are just lists of characters: ~"c₀c₁…cₙ" ≈ ['c₀', …, 'cₙ']~. 241 | - Hence, all list methods work for strings. 242 | 243 | ** Pattern Matching on Lists 244 | *Pattern matching on lists* 245 | #+BEGIN_SRC haskell 246 | prod [] = 1 247 | prod (x:xs) = x * prod xs 248 | 249 | fact n = prod [1 .. n] 250 | #+END_SRC 251 | 252 | If your function needs a case with a list of say, length 3, then you can match 253 | directly on that /shape/ via ~[x, y, z]~ ---which is just an abbreviation for the 254 | shape ~x:y:z:[]~. Likewise, if we want to consider lists of length /at least 3/ then 255 | we match on the shape ~x:y:z:zs~. E.g., define the function that produces the 256 | maximum of a non-empty list, or the function that removes adjacent duplicates 257 | ---both require the use of guards. 258 | 259 | ** Common Methods on Lists 260 | # -- Indexing 261 | # -- Gluing two lists together 262 | # -- Flattening a list of lists 263 | #+BEGIN_SRC haskell 264 | [x₀, …, xₙ] !! i = xᵢ 265 | [x₀, …, xₙ] ++ [y₀, …, yₘ] = [x₀, …, xₙ, y₀, …, yₘ] 266 | concat [xs₀, …, xsₙ] = xs₀ ++ ⋯ ++ xsₙ 267 | 268 | {- Partial functions -} 269 | head [x₀, …, xₙ] = x₀ 270 | tail [x₀, …, xₙ] = [x₁, …, xₙ] 271 | init [x₀, …, xₙ] = [x₀, …, xₙ₋₁] 272 | last [x₀, …, xₙ] = xₙ 273 | 274 | take k [x₀, …, xₙ] = [x₀, …, xₖ₋₁] 275 | drop k [x₀, …, xₙ] = [xₖ, …, xₙ] 276 | 277 | sum [x₀, …, xₙ] = x₀ + ⋯ + xₙ 278 | prod [x₀, …, xₙ] = x₀ * ⋯ * xₙ 279 | reverse [x₀, …, xₙ] = [xₙ, …, x₀] 280 | elem x [x₀, …, xₙ] = x == x₀ || ⋯ || x == xₙ 281 | 282 | zip [x₀, …, xₙ] [y₀, …, yₘ] = [(x₀, y₀), …, (xₖ, yₖ)] where k = n `min` m 283 | unzip [(x₀, y₀), …, (xₖ, yₖ)] = ([x₀, …, xₖ], [y₀, …, yₖ]) 284 | #+END_SRC 285 | 286 | [[https://en.wikipedia.org/wiki/Conjugacy_class][*Duality*]]: Let ~∂f = reverse . f . reverse~, then ~init = ∂ tail~ and {{{newline}}} 287 | ~take k = ∂ (drop k)~; even ~pure . head = ∂ (pure . last)~ where ~pure x = [x]~. 288 | 289 | * List ‘Design Patterns’ 290 | 291 | Many functions have the same ‘form’ or ‘design pattern’, a fact which is 292 | taken advantage of by defining /higher-order functions/ to factor out the 293 | structural similarity of the individual functions. 294 | 295 | ** Map 296 | 297 | ~map f xs = [f x | x <- xs]~ 298 | - Transform all elements of a list according to the function ~f~. 299 | 300 | ** Filter 301 | ~filter p xs = [x | x <- xs, p x]~ 302 | - Keep only the elements of the list that satisfy the predicate ~p~. 303 | - ~takeWhile p xs~ ≈ Take elements of ~xs~ that satisfy ~p~, but stop stop at 304 | the first element that does not satisfy ~p~. 305 | - ~dropWhile p xs~ ≈ Drop all elements until you see one that does not satisfy 306 | the predicate. 307 | - ~xs = takeWhile p xs ++ dropWhile p xs~. 308 | 309 | ** Fold 310 | Right-folds let us ‘sum’ up the elements of the list, associating to the right. 311 | #+BEGIN_SRC haskell 312 | foldr (⊕) e ≈ λ (x₀ : (x₁ : (… : (xₙ : [])))) 313 | → (x₀ ⊕ (x₁ ⊕ (… ⊕ (xₙ ⊕ e)))) 314 | #+END_SRC 315 | 316 | This function just replaces cons ~“∶”~ and ~[]~ with ~⊕~ and ~e~. That's all. 317 | * E.g., replacing ~:,[]~ with themselves does nothing: ~foldr (:) [] = id~. 318 | 319 | #+latex: \newpage 320 | /All functions on lists can be written as folds!/ 321 | #+BEGIN_SRC haskell 322 | h [] = e ∧ h (x:xs) = x ⊕ h xs 323 | ≡ h = foldr (λ x rec_call → x ⊕ rec_call) e 324 | #+END_SRC 325 | + Look at the two cases of a function and move them to the two 326 | first arguments of the fold. 327 | - ~map f = foldr (λ x ys → f x : ys) []~ 328 | - ~filter p = foldr (λ x ys → if (p x) then (x:ys) else ys) []~ 329 | - ~takeWhile p = foldr (λ x ys → if (p x) then (x:ys) else []) []~ 330 | # - E.g., ~dropWhile p = foldr (λ x ys → if (p x) then ys else (x:ys)) []~. 331 | # # 332 | You can also fold leftward, i.e., by associating to the left: 333 | #+BEGIN_SRC haskell 334 | foldl (⊕) e ≈ λ (x₀ : (x₁ : (… : (xₙ : [])))) 335 | → (((e ⊕ x₀) ⊕ x₁) ⊕ … ) ⊕ xₙ 336 | #+END_SRC 337 | Unless the operation ~⊕~ is associative, the folds are generally different. 338 | + E.g., ~foldl (/) 1 [1..n] ≈ 1 / n!~ where ~n ! = product [1..n]~. 339 | + E.g., ~-55 = foldl (-) 0 [1..10] ≠ foldr (-) 0 [1..10] = -5~. 340 | 341 | If ~h~ swaps arguments ---~h(x ⊕ y) = h y ⊕ h x~--- then ~h~ swaps folds: 342 | {{{newline}}} 343 | ~h . foldr (⊕) e = foldl (⊝) e′~ where ~e′ = h e~ and ~x ⊝ y = x ⊕ h y~. 344 | 345 | E.g., ~foldl (-) 0 xs = - (foldr (+) 0 xs) = - (sum xs)~ 346 | {{{newline}}} and ~n ! = foldr (*) 1 [1..n] = 1 / foldl (/) 1 [1..n]~. 347 | 348 | | /( Floating points are a leaky abstraction! )/ | 349 | 350 | * Algebraic data types 351 | 352 | When we have ‘possible scenarios’, we can make a type to consider each option. 353 | E.g., ~data Door = Open | Closed~ makes a new datatype with two different values. 354 | Under the hood, ~Door~ could be implemented as integers and ~Open~ is 0 and ~Closed~ 355 | is 1; or any other implementation ---/all that matters/ is that we have a new 356 | type, ~Door~, with two different values, ~Open~ and ~Closed~. 357 | 358 | Usually, our scenarios contain a ‘payload’ of additional information; e.g., ~data 359 | Door2 = Open | Ajar Int | Closed~. Here, we have a new way to construct ~Door~ 360 | values, such as ~Ajar 10~ and ~Ajar 30~, that we could interpret as denoting how far 361 | the door is open/. Under the hood, ~Door2~ could be implemented as pairs of 362 | integers, with ~Open~ being ~(0,0)~, ~Ajar n~ being ~(1, n)~, and ~Closed~ being ~(2, 0)~ 363 | ---i.e., as the pairs “(value position, payload data)”. Unlike functions, a 364 | value construction such as ~Ajar 10~ cannot be simplified any further; just as the 365 | list value ~1:2:3:[]~ cannot be simplified any further. Remember, the 366 | representation under the hood does not matter, what matters is that we have 367 | three possible /construction forms/ of ~Door2~ values. 368 | 369 | Languages, such as C, which do not support such an “algebraic” approach, 370 | force you, the user, to actually choose a particular representation ---even 371 | though, it does not matter, since we only want /a way to speak of/ “different 372 | cases, with additional information”. 373 | 374 | In general, we declare the following to get an “enumerated type with payloads”. 375 | #+BEGIN_SRC haskell 376 | data D = C₀ τ₁ τ₂ … τₘ | C₁ ⋯ | Cₙ ⋯ deriving Show 377 | #+END_SRC 378 | There are =n= constructors ~Cᵢ~ that make /different/ values of type ~D~; e.g., ~C₀ x₁ x₂ 379 | … xₘ~ is a ~D~-value whenever each ~xᵢ~ is a ~τᵢ~-value. The ~“deriving Show”~ at the end 380 | of the definition is necessary for user-defined types to make sure that values 381 | of these types can be printed in a standard form. 382 | 383 | We may now define functions on ~D~ by pattern matching on the possible ways to 384 | /construct/ values for it; i.e., by considering the cases ~Cᵢ~. 385 | 386 | In-fact, we could have written ~data D α₁ α₂ … αₖ = ⋯~, so that we speak of “D 387 | values /parameterised/ by types αᵢ”. E.g., “lists whose elements are of type α” is 388 | defined by ~data List α = Nil | Cons α (List α)~ and, for example, ~Cons 1 (Cons 2 389 | Nil)~ is a value of ~List Int~, whereas ~Cons 'a' Nil~ is of type ~List Char~. ---The 390 | ~List~ type is missing the ~“deriving Show”~, see below for how to /mixin/ such a 391 | feature. 392 | 393 | For example, suppose we want to distinguish whether we have an α-value or a 394 | β-value, we use ~Either~. Let's then define an example /infix/ function using 395 | pattern matching. 396 | #+BEGIN_SRC haskell 397 | data Either α β = Left α | Right β 398 | 399 | (+++) :: (α → α′) → (β → β′) → Either α β → Either α′ β′ 400 | (f +++ g) (Left x) = Left $ f x 401 | (f +++ g) (Right x) = Right $ g x 402 | 403 | right :: (β → τ) → Either α β → Either α τ 404 | right f = id +++ f 405 | #+END_SRC 406 | The above ~(+++)~ can be found in ~Control.Arrow~ and is also known as ~either~ in the 407 | standard library. 408 | 409 | * Typeclasses and overloading 410 | 411 | /Overloading/ is using the same name to designate operations “of the same nature” 412 | on values of different types. 413 | 414 | E.g., the ~show~ function converts its argument into a string; however, it is not 415 | polymorphic: We cannot define ~show :: α → String~ with one definition since some 416 | items, like functions or infinite datatypes, cannot be printed and so this is 417 | not a valid type for the function ~show~. 418 | 419 | Haskell solves this by having ~Show~ /typeclass/ whose /instance types/ ~α~ each 420 | implement a definition of the /class method/ ~show~. The type of ~show~ is written 421 | ~Show α => α -> String~: /Given an argument of type ~α~, look in the global listing of 422 | ~Show~ instances, find the one for ~α~, and use that;/ if ~α~ has no ~Show~ instance, 423 | then we have a type error. One says “the type variable ~α~ has is /restricted/ to be 424 | a ~Show~ instance” ---as indicated on the left side of the ~“=>”~ symbol. 425 | 426 | E.g., for the ~List~ datatype we defined, we may declare it to be ‘showable’ like 427 | so: 428 | #+begin_quote org 429 | #+BEGIN_SRC haskell -n 1 430 | instance Show a => Show (List a) where 431 | show Nil = "Nope, nothing here" 432 | show (Cons x xs) = "Saw " ++ show x ++ ", then " ++ show xs 433 | #+END_SRC 434 | #+end_quote 435 | That is: 436 | 1. /If ~a~ is showable, then ~List a~ is also showable./ 437 | 2. /Here's how to show ~Nil~ directly./ 438 | 3. /We show ~Cons x xs~ by using the ~show~ of ~a~ on ~x~, then recursively showing ~xs~./ 439 | 440 | | | Common Typeclasses | 441 | |-------------+----------------------------------------------------| 442 | | ~Show~ | Show elements as strings, ~show~ | 443 | | ~Read~ | How to read element values from strings, ~read~ | 444 | | ~Eq~ | Compare elements for equality, ~==~ | 445 | | ~Num~ | Use literals ~0, 20, …,~ and arithmetic ~+, *, -~ | 446 | | ~Ord~ | Use comparison relations ~>, <, >=, <=~ | 447 | | ~Enum~ | Types that can be listed, ~[start .. end]~ | 448 | | ~Monoid~ | Types that model ‘(untyped) composition’ | 449 | | ~Functor~ | /Type formers/ that model effectful computation | 450 | | ~Applicative~ | Type formers that can sequence effects | 451 | | ~Monad~ | Type formers that let effects depend on each other | 452 | 453 | The ~Ord~ typeclass is declared ~class Eq a => Ord a where ⋯~, so that all ordered 454 | types are necessarily also types with equality. One says ~Ord~ is a /subclass/ of 455 | ~Eq~; and since subclasses /inherit/ all functions of a class, we may always replace 456 | ~(Eq a, Ord a) => ⋯~ by ~Ord a => ⋯~. 457 | 458 | You can of-course define your own typeclasses; e.g., the ~Monoid~ class in Haskell 459 | could be defined as follows. 460 | #+BEGIN_SRC haskell 461 | class Semigroup a where 462 | (<>) :: a -> a -> a {- A way to “compose” elements together -} 463 | {- Axiom: (x <> y) <> z = x <> (y <> z) -} 464 | 465 | class Semigroup a => Monoid a where 466 | mempty :: a {- Axiom: This is a ‘no-op’, identity, for composition <> -} 467 | #+END_SRC 468 | Example monoids ~(α, <>, mempty)~ include ~(Int, +, 0)~, ~([α], ++, [])~, and 469 | {{{newline}}} (Program statements, sequence “;”, the empty statement) ---this 470 | last example is approximated as ~Term~ with ‘let-in’ clauses at the end of this 471 | cheatsheet. /Typeclasses are interfaces, possibly with axioms specifying their 472 | behaviour./ 473 | 474 | As shown earlier, Haskell provides a the ~deriving~ mechanism for making it easier 475 | to define instances of typeclasses, such as ~Show, Read, Eq, Ord, Enum~. How? 476 | Constructor names are printed and read as written as written in the ~data~ 477 | declaration, two values are equal if they are formed by the same construction, 478 | one value is less than another if the constructor of the first is declared in 479 | the ~data~ definition before the constructor of the second, and similarly for 480 | listing elements out. 481 | * Functor 482 | 483 | /Functors are type formers that “behave” like collections: We can alter their/ 484 | /“elements” without messing with the ‘collection structure’ or ‘element 485 | positions’./ The well-behavedness constraints are called /the functor axioms/. 486 | #+BEGIN_SRC haskell 487 | class Functor f where 488 | fmap :: (α → β) → f α → f β 489 | 490 | (<$>) = fmap {- An infix alias -} 491 | #+END_SRC 492 | 493 | The axioms cannot be checked by Haskell, so we can form instances that fail to 494 | meet the implicit specifications ---two examples are below. 495 | 496 | ** Identity Axiom 497 | 498 | *Identity Law*: ~fmap id = id~ 499 | 500 | /Doing no alteration to the contents of a collection does nothing to the collection./ 501 | 502 | This ensures that “alterations don't needlessly mess with element values” 503 | e.g., the following is not a functor since it does. 504 | #+BEGIN_SRC haskell :tangle probably.hs 505 | {- I probably have an item -} 506 | data Probably a = Chance a Int 507 | 508 | instance Functor Probably where 509 | fmap f (Chance x n) = Chance (f x) (n `div` 2) 510 | #+END_SRC 511 | 512 | ** Fusion Axiom 513 | *Fusion Law:* ~fmap f . fmap g = fmap (f . g)~ 514 | 515 | /Reaching into a collection and altering twice is the same as reaching in and 516 | altering once./ 517 | 518 | This ensures that “alterations don't needlessly mess with collection structure”; 519 | e.g., the following is not a functor since it does. 520 | 521 | #+BEGIN_SRC haskell :tangle pocket.hs 522 | import Prelude hiding (Left, Right) 523 | 524 | {- I have an item in my left or my right pocket -} 525 | data Pocket a = Left a | Right a 526 | 527 | instance Functor Pocket where 528 | fmap f (Left x) = Right (f x) 529 | fmap f (Right x) = Left (f x) 530 | #+END_SRC 531 | 532 | ** Functors do not necessarily ‘contain’ anything 533 | 534 | It is important to note that functors model well-behaved container-like types, 535 | but of-course the types do not actually need to contain anything at all! E.g., 536 | the following is a valid functor. 537 | #+BEGIN_SRC haskell :tangle Liar.hs 538 | {- “I totally have an α-value, it's either here or there.” Lies! -} 539 | data Liar α = OverHere Int | OverThere Int 540 | 541 | instance Functor Liar where 542 | fmap f (OverHere n) = OverHere n 543 | fmap f (OverThere n) = OverThere n 544 | #+END_SRC 545 | Notice that if we altered ~n~, say by dividing it by two, then we break the 546 | identity law; and if we swap the constructors, then we break the fusion law. 547 | Super neat stuff! 548 | 549 | In general, functors take something boring and generally furnish it with 550 | ‘coherent’ structure, but *there is not necessarily an α ‘inside’ f α*. 551 | E.g., ~f α = (ε → α)~ has as values “recipes for forming an α-value”, 552 | but unless executed, there is no ~α~-value. 553 | 554 | ** Misc results about Functors 555 | 556 | #+latex: \vspace{0.5em} 557 | + ~fmap f xs~ ≈ /for each/ element ~x~ in the ‘collection’ ~xs~, yield ~f x~. 558 | + Haskell can usually ~derive~ functor instances since they are [[http://archive.fo/U8xIY][unique]]: Only one 559 | possible definition of ~fmap~ will work. 560 | :Proof: 561 | Suppose we have a functor f and another function 562 | 563 | foo :: (a -> b) -> f a -> f b 564 | 565 | Then as a consequence of the free theorem for foo, 566 | for any f :: a -> b and any g :: b -> c. 567 | 568 | foo (g . f) = fmap g . foo f 569 | 570 | In particular, if foo id = id, then 571 | 572 | foo g = foo (g . id) = fmap g . foo id = fmap g . id = fmap g 573 | :End: 574 | + Reading the functor axioms left-to-right, they can be seen as /optimisation laws/ 575 | that make a program faster by reducing work. 576 | + The two laws together say /fmap distributes over composition/: {{{newline}}} 577 | ~fmap (f₁ . f₂ . ⋯ . fₙ) = fmap f₁ . ⋯ . fmap fₙ~ for ~n ≥ 0~. 578 | 579 | *Naturality Theorems:* If ~p ∷ f a → g a~ for some /functors/ ~f~ and ~g~, {{{newline}}} 580 | then ~fmap f . p = p . fmap f~ for any /function/ ~f~. 581 | 582 | Hence, any generic property ~p ∷ f α → ε~ is invariant over fmaps: 583 | ~p(fmap f xs) = p xs~. E.g., the length of a list does not change even when an 584 | fmap is applied. 585 | # - This is the naturality theorem for ~p~ where ~g a = ε~ is the constantly-~ε~ functor. 586 | 587 | * Functor Examples 588 | 589 | Let ~f₁, f₂~ be functors and ~ε~ be a given type. 590 | 591 | | Type Former | ~f α~ | ~f <$> x~ | 592 | |-------------+----------------------+-------------------------------------| 593 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Identity.html#t:Identity][Identity]] | ~α~ | ~f <$> x = f x~ | 594 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Applicative.html#t:Const][Constant]] | ~ε~ | ~f <$> x = x~ | 595 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-List.html][List]] | ~[α]~ | ~f <$> [x₀, …, xₙ] = [f x₀, …, f xₙ]~ | 596 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Either.html#t:Either][Either]] | ~Either ε α~ | ~f <$> x = right f~ | 597 | |-------------+----------------------+-------------------------------------| 598 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Product.html#t:Product][Product]] | ~(f₁ α, f₂ α)~ | ~f <$> (x, y) = (f <$> x, f <$> y)~ | 599 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Compose.html#t:Compose][Composition]] | ~f₁ (f₂ α)~ | ~f <$> x = (fmap f) <$> x~ | 600 | | [[http://comonad.com/reader/2012/abstracting-with-applicatives/][Sum]] | ~Either (f₁ α) (f₂ α)~ | ~f <$> ea = f +++ f~ | 601 | |-------------+----------------------+-------------------------------------| 602 | | [[http://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Writer-Lazy.html#g:2][Writer]] | ~(ε, α)~ | ~f <$> (e, x) = (e, f x)~ | 603 | | [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Reader.html][Reader]] | ~ε → α~ | ~f <$> g = f . g~ | 604 | | [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-State-Lazy.html#g:2][State]] | ~ε → (ε, α)~ | ~f <$> g = second f . g~ | 605 | 606 | Notice that writer is the product of the constant and the identity functors. 607 | 608 | Unlike reader, the type former ~f α = α → ε~ is /not/ a functor since there is no 609 | way to implement ~fmap~. In contrast, ~f α = (α → ε, α)~ /does/ have an implementation 610 | of ~fmap~, but it is not lawful. 611 | # It fails the identity axiom. 612 | 613 | 614 | #+latex: \vspace{-0.0em} 615 | * Applicative 616 | # ---Protecting against invalid input 617 | #+latex: \vspace{-0.5em} 618 | 619 | /Applicatives are collection-like types that can apply collections of functions 620 | to collections of elements./ 621 | 622 | In particular, /applicatives can fmap over multiple arguments/; e.g., if we try to 623 | add ~Just 2~ and ~Just 3~, we find =(+) <$> Just 2 :: Maybe (Int → Int)= and this is 624 | not a function and so cannot be applied further to ~Just 3~ to get ~Just 5~. 625 | We have both the function and the value wrapped up, so we need a way to apply 626 | the former to the latter. The answer is ~(+) <$> Just 2 <*> Just 3~. 627 | 628 | #+BEGIN_SRC haskell 629 | class Functor f => Applicative f where 630 | pure :: a -> f a 631 | (<*>) :: f (a -> b) -> f a -> f b {- “apply” -} 632 | 633 | {- Apply associates to the left: p <*> q <*> r = (p <*> q) <*> r) -} 634 | #+END_SRC 635 | 636 | The method ~pure~ lets us inject values, to make ‘singleton collections’. 637 | 638 | # Main idea 639 | + /Functors transform values inside collections; applicatives can additionally 640 | combine values inside collections./ 641 | + Exercise: If ~α~ is a monoid, then so too is ~f α~ for any applicative ~f~. 642 | 643 | ** Axioms 644 | The applicative axioms ensure that apply behaves like usual functional application: 645 | 646 | + Identity: ~pure id <*> x = x~ ---c.f., ~id x = x~ 647 | + Homomorphism: ~pure f <*> pure x = pure (f x)~ ---it really is function application 648 | on pure values! 649 | - Applying a non-effectful function to a non-effectful argument in an effectful 650 | context is the same as just applying the function to the argument and then 651 | injecting the result into the content. 652 | + Interchange: ~p <*> pure x = pure ($ x) <*> p~ ---c.f., ~f x = ($ x) f~ 653 | - Functions ~f~ take ~x~ as input ≈ Values ~x~ project functions ~f~ to particular values 654 | - When there is only one effectful component, then it does not matter whether 655 | we evaluate the function first or the argument first, there will still only be 656 | one effect. 657 | - Indeed, this is equivalent to the law: ~pure f <*> q = pure (flip ($)) <*> q <*> pure f~. 658 | 659 | + Composition: ~pure (.) <*> p <*> q <*> r = p <*> (q <*> r)~ 660 | {{{newline}}} ---c.f., ~(f . g) . h = f . (g . h)~. 661 | 662 | If we view ~f α~ as an “effectful computation on α”, then the above laws ensure 663 | ~pure~ creates an “effect free” context. E.g., if ~f α = [α]~ is considered 664 | “nondeterminstic α-values”, then ~pure~ just treats usual α-values as 665 | nondeterminstic but with no ambiguity, and ~fs <*> xs~ reads “if we 666 | nondeterminsticly have a choice ~f~ from ~fs~, and we nondeterminsticly an ~x~ from 667 | ~xs~, then we nondeterminsticly obtain ~f x~.” More concretely, if I'm given 668 | randomly addition or multiplication along with the argument 3 and another 669 | argument that could be 2, 4, or 6, then the result would be obtained by 670 | considering all possible combinations: ~[(+), (*)] <*> pure 3 <*> [2, 4, 6] = 671 | [5,7,9,6,12,18]~. The name ~“<*>”~ is suggestive of this ‘cartesian product’ nature. 672 | 673 | Given a definition of apply, the definition of ~pure~ may be obtained 674 | by unfolding the identity axiom. 675 | # Given a definition of apply, the definition of ~pure~ is then unique. 676 | # Proof? 677 | 678 | # Using these laws, we can define a lawful definition of ~fmap~ 679 | # but lawful ~fmap~'s 680 | Using these laws, we regain the original ~fmap~ ---since ~fmap~'s are [[http://archive.fo/U8xIY][unique]] in 681 | Haskell--- thereby further cementing that applicatives model “collections that 682 | can be functionally applied”: ~f <$> x = pure f <*> x~. ( Hence, every applicative 683 | is a functor whether we like it or not. ) 684 | - The identity applicative law is then just the identity law of functor. 685 | # : ~id <$> x = x~. 686 | - The homomorphism law now becomes: ~pure . f = fmap f . pure~. 687 | # i.e., ~λ x → pure (f x) = λ x → fmap f (pure x)~. 688 | * This is the “naturality law” for ~pure~. 689 | :Proof: 690 | fmap f (pure x) 691 | = f <$> pure x 692 | = pure f <*> pure x 693 | = pure (f x) 694 | :End: 695 | 696 | ** Canonical Form -- =liftN= 697 | 698 | [[http://www.staff.city.ac.uk/~ross/papers/Applicative.pdf][The laws]] may be interpreted as left-to-right rewrite rules and so are a 699 | procedure for transforming any applicative expression into the canonical form 700 | of “a pure function applied to effectful arguments”: ~pure f <*> x₁ <*> ⋯ <*> 701 | xₙ~. In this way, one can compute in-parallel the, necessarily independent, ~xᵢ~ 702 | then combine them together. 703 | 704 | Notice that the canonical form generalises ~fmap~ to ~n~-arguments: {{{newline}}} 705 | Given ~f ∷ α₁ → ⋯ → αₙ → β~ and ~xᵢ ∷ f αᵢ~, we obtain an ~(f β)~-value. {{{newline}}} 706 | The case of ~n = 2~ is called ~liftA2~, ~n = 1~ is just ~fmap~, and for ~n = 0~ we have 707 | ~pure~! 708 | 709 | :More: 710 | The ~ApplicativeDo~ extension permits a different 711 | style for the canonical form: 712 | #+BEGIN_SRC haskell 713 | do v₁ ← x₁ 714 | ⋮ 715 | vₙ ← xₙ 716 | pure (f v₁ v₂ … vₙ) 717 | #+END_SRC 718 | :End: 719 | # For more details, see Applicative Programming with Effects, by Conor McBride 720 | # and Ross Paterson. 721 | ** Monoidal Presentation 722 | 723 | Notice that ~lift2A~ is essentially the cartesian product in the setting of lists, 724 | or ~(<&>)~ below ---c.f., ~sequenceA :: Applicative f ⇒ [f a] → f [a]~. 725 | 726 | #+BEGIN_SRC haskell 727 | (<&>) :: f a → f b → f (a, b) {- Not a standard name! -} 728 | (<&>) = liftA2 (,) -- i.e., p <&> q = (,) <$> p <*> q 729 | #+END_SRC 730 | This is a pairing operation with properties of ~(,)~ mirrored at the applicative level: 731 | #+BEGIN_SRC haskell 732 | {- Pure Pairing -} pure x <&> pure y = pure (x, y) 733 | {- Naturality -} (f &&& g) <$> (u <&> v) = (f <$> u) <&> (g <&> v) 734 | 735 | {- Left Projection -} fst <$> (u <&> pure ()) = u 736 | {- Right Projection -} snd <$> (pure () <&> v) = v 737 | {- Associtivity -} assocl <$> (u <&> (v <&> w)) = (u <&> v) <&> w 738 | #+END_SRC 739 | :PurePairing_Proof: 740 | #+BEGIN_SRC haskell 741 | pure x <&> pure y 742 | = (,) <$> pure x <*> pure y 743 | = pure (,) <*> pure x <*> pure y 744 | = pure (x,) <*> pure y 745 | = pure (x,y) 746 | #+END_SRC 747 | :End: 748 | The final three laws above suffice to prove the original applicative axioms, and so 749 | we may define ~p <*> q = uncurry ($) <$> (p <&> q)~. 750 | # Naturality, in the context of Haskell, is a free theorem. 751 | 752 | * Applicative Examples 753 | 754 | Let ~f₁, f₂~ be functors and let ~ε~ a type. 755 | 756 | | Functor | ~f α~ | ~f <*> x~ | 757 | |-------------+----------------------+-----------------------------------------| 758 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Identity.html#t:Identity][Identity]] | ~α~ | ~f <*> x = f x~ | 759 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Applicative.html#t:Const][Constant]] | ~ε~ | ~e <*> d = e <> d~ | 760 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-List.html][List]] | ~[α]~ | =fs <*> xs = [f x ∣ f <- fs, x <- xs]= | 761 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Either.html#t:Either][Either]] | ~Either ε α~ | ~ef <*> ea = right (λ f → right f ea) ef~ | 762 | |-------------+----------------------+-----------------------------------------| 763 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Compose.html#t:Compose][Composition]] | ~f₁ (f₂ α)~ | ~f <*> x = (<*>) <$> f <*> x~ | 764 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Product.html#t:Product][Product]] | ~(f₁ α, f₂ α)~ | ~(f, g) <*> (x, y) = (f <*> x, g <*> y)~ | 765 | | [[http://comonad.com/reader/2012/abstracting-with-applicatives/][Sum]] | ~Either (f₁ α) (f₂ α)~ | Challenge: Assume ~η ∷ f₁ a → f₂ a~ | 766 | |-------------+----------------------+-----------------------------------------| 767 | | [[http://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Writer-Lazy.html#g:2][Writer]] | ~(ε, α)~ | ~(a , f) <*> (b, x) = (a <> b, f x)~ | 768 | | [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Reader.html][Reader]] | ~ε → α~ | ~f <*> g = λ e → f e (g e)~ ---c.f., ~SKI~ | 769 | | [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-State-Lazy.html#g:2][State]] | ~ε → (ε, α)~ | ~sf <*> sa = λ e → let (e′, f) = sf e~ | 770 | | | | ~in second f (sa e′)~ | 771 | 772 | In the writer and constant cases, we need ~ε~ to also be a monoid. 773 | When ε is /not/ a monoid, then those two constructions give examples of functors 774 | that are /not/ applicatives ---since there is no way to define ~pure~. 775 | In contrast, ~f α = (α → ε) → Maybe ε~ is not an applicative since no 776 | definition of apply is lawful. 777 | 778 | Since readers ~((->) r)~ are applicatives, we may, for example, write ~(⊕) <$> f 779 | <*> g~ as a terse alternative to the “pointwise ⊕” method ~λ x → f x ⊕ g x~. E.g., 780 | using ~(&&)~ gives a simple way to chain predicates. 781 | :Indeed: 782 | #+BEGIN_SRC haskell 783 | (⊕) <$> f <*> g 784 | = (pure (⊕) <*> f) <*> g 785 | = λ x → (pure (⊕) <*> f) x (g x) 786 | = λ x → pure (⊕) x (f x) (g x) 787 | = λ x → (⊕) (f x) (g x) 788 | = λ x → f x ⊕ g x 789 | #+END_SRC 790 | 791 | :End: 792 | 793 | :Table_with_pure: 794 | | Functor | ~f α~ | ~pure a~ | ~f <*> x~ | 795 | |-------------+----------------------+------------------+----------------------------------------| 796 | | Identity | ~α~ | ~a~ | ~f x~ | 797 | | Constant | ~ε~ | ~mempty~ | ~f <> x~ | 798 | | List | ~[α]~ | ~[a]~ | =fs <*> xs = [f x ∣ f <- fs, x <- xs]= | 799 | | Either | ~Either ε α~ | ~Right a~ | ~right (λ f → right f ea) ef~ | 800 | |-------------+----------------------+------------------+----------------------------------------| 801 | | Composition | ~f₁ (f₂ α)~ | ~pure (pure a)~ | ~f <*> x = (<*>) <$> f <*> x~ | 802 | | Product | ~(f₁ α, f₂ α)~ | ~(pure a, pure a)~ | ~(f, g) <*> (x, y) = (f <*> x, g <*> y)~ | 803 | | Sum | ~Either (f₁ α) (f₂ α)~ | | ~f <$> ea = f +++ f~ | 804 | |-------------+----------------------+------------------+----------------------------------------| 805 | | Writer | ~(ε, α)~ | ~(mempty, a)~ | ~(a , f) <*> (b, x) = (a <> b, f x)~ | 806 | | Reader | ~ε → α~ | ~λ _ → a~ | ~f <*> g = λ x → f x (g x)~ --i.e., ~S~ | 807 | :End: 808 | 809 | * ~Do~-Notation ---Subtle difference between applicatives and monads 810 | Recall the ~map~ operation on lists, we could define it ourselves: 811 | #+BEGIN_SRC haskell :tangle delme.hs 812 | map' :: (α -> β) -> [α] -> [β] 813 | map' f [] = [] 814 | map' f (x:xs) = let y = f x 815 | ys = map' f xs 816 | in (y:ys) 817 | #+END_SRC 818 | If instead the altering function ~f~ returned effectful results, 819 | then we could gather the results along with the effect: 820 | #+BEGIN_SRC haskell :tangle delme1.hs 821 | {-# LANGUAGE ApplicativeDo #-} 822 | 823 | mapA :: Applicative f => (a -> f b) -> [a] -> f [b] 824 | mapA f [] = pure [] 825 | mapA f (x:xs) = do y <- f x 826 | ys <- mapA f xs 827 | pure (y:ys) 828 | {- ≈ (:) <$> f x <*> mapA f xs -} 829 | #+END_SRC 830 | 831 | Applicative syntax can be a bit hard to write, whereas ~do~-notation is more 832 | natural and reminiscent of the imperative style used in defining ~map'~ above. For 833 | instance, the intuition that ~fs <*> ps~ is a cartesian product is clearer in 834 | do-notation: ~fs <*> ps ≈ do {f ← fs; x ← ps; pure (f x)}~ where the right side is 835 | read /“for-each f in fs, and each x in ps, compute f x”/. 836 | 837 | #+latex: \columnbreak 838 | # “Desugaring Haskell’s do-Notation into Applicative Operations” 839 | [[https://dl.acm.org/doi/pdf/10.1145/3241625.2976007][In-general]], ~do {x₁ ← p₁; …; xₙ ← pₙ; pure e} ≈ pure (λ x₁ … xₙ → e) <*> p₁ <*> ⋯ 840 | <*> pₙ~ *provided* ~pᵢ~ does not mention ~xⱼ~ for ~j < i~; but =e= may refer to all ~xᵢ~. If 841 | any ~pᵢ~ mentions an earlier ~xⱼ~, then we could not translate the ~do~-notation into 842 | an applicative expression. 843 | 844 | If ~do {x ← p; y ← qx; pure e}~ has ~qx~ being an expression *depending* on ~x~, 845 | then we could say this is an abbreviation for ~(λ x → (λ y → e) <$> qx) <$> p~ 846 | but this is of type ~f (f β))~. Hence, to allow later computations to depend 847 | on earlier computations, we need a method ~join :: f (f α) → f α~ with which 848 | we define {{{newline}}} ~do {x ← p; y ← qx; pure e} ≈ join $ ~(λ x -> (λ y → e) <$> qx) <$> p~. 849 | 850 | Applicatives with a ~join~ are called monads and they give us a *“programmable 851 | semicolon”*. Since later items may depend on earlier ones, ~do {x ← p; y ← q; 852 | pure e}~ could be read /“let x be the value of computation p, let y be the value 853 | of computation q, then combine the values via expression e”/. Depending on how 854 | ~<*>~ is implemented, such ‘let declarations’ could short-circuit (~Maybe~) or be 855 | nondeterministic (~List~) or have other effects such as altering state. 856 | 857 | As the ~do~-notation clearly shows, the primary difference between =Monad= and 858 | =Applicative= is that =Monad= allows dependencies on previous results, whereas 859 | =Applicative= does not. 860 | 861 | :TypeChecking: 862 | #+BEGIN_SRC haskell :tangle delme_0.hs 863 | p₁ :: Applicative f => f α 864 | p₁ = undefined 865 | 866 | p₂ :: Applicative f => α -> f β 867 | p₂ = undefined 868 | 869 | data C = C 870 | 871 | e :: α -> β -> C 872 | e = undefined 873 | 874 | this :: Applicative f => f (f C) 875 | -- this = e <$> p₁ <*> undefined 876 | this = (\ x₁ -> e x₁ <$> p₂ x₁) <$> p₁ 877 | #+END_SRC 878 | :End: 879 | 880 | ** Do-notation with tuples and functions 881 | 882 | Do-syntax also works with tuples and functions --c.f., reader monad below--- 883 | since they are monadic; e.g., every clause ~x <- f~ in a functional do-expression 884 | denotes the resulting of applying ~f~ to the (implicit) input. 885 | More concretely: 886 | #+BEGIN_SRC haskell 887 | go :: (Show a, Num a) => a -> (a, String) 888 | go = do {x <- (1+); y <- show; return (x, y)} 889 | 890 | -- go 3 = (4, "3") 891 | #+END_SRC 892 | 893 | Likewise, tuples, lists, etc. 894 | 895 | * Formal Definition of ~Do~-Notation 896 | 897 | For a general applicative ~f~, a ~do~ expression has the form ~do {C; r}~, where ~C~ is 898 | a (possibly empty) list of commands separated by semicolons, and ~r~ is an 899 | expression of type ~f β~, which is also the type of the entire ~do~ expression. Each 900 | command takes the form ~x ← p~, where ~x~ is a variable, or possibly a pattern; if ~p 901 | :: f α~ then ~x :: α~. In the particular case of the anonymous variable, ~_ ← p~ may 902 | be abbreviated to ~p~. 903 | 904 | The translation of a ~do~ expression into ~<*>/join~ operations and ~where~ clauses is 905 | governed by three rules ---the last one only applies in the setting of a monad. 906 | #+BEGIN_SRC haskell 907 | (1) do {r} = r 908 | (2A) do {x ← p; C; r} = q <*> p where q x = do {C; r} --Provided x ∉ C 909 | (2M) do {x ← p; C; r} = join $ map q p where q x = do {C; r} 910 | 911 | {- Fact: When x ∉ C, (2A) = (2M). -} 912 | #+END_SRC 913 | 914 | By definition chasing and induction on the number of commands ~C~, we have: 915 | #+BEGIN_SRC haskell 916 | [CollapseLaw] do {C; do {D; r}} = do {C; D; r} 917 | #+END_SRC 918 | :Proof: 919 | #+BEGIN_SRC haskell 920 | {- Proof: 921 | [base] do {do {D; r}} = do {D; r} ✓ 922 | [ind] do {x ← p; C′; do {D; r}} -- case: x ∉ C 923 | = q <*> p where q x = do {C′; do {D; r}} 924 | = q <*> p where q x = do {C′; D; r} 925 | = do {x ← p; C′; D; r} ✓ 926 | [ind] do {x ← p; C′; do {D; r}} -- case: x may be in C 927 | = join $ map q p where q x = do {C′; do {D; r}} 928 | = join $ map q p where q x = do {C′; D; r} 929 | = do {x ← p; C′; D; r} ✓ 930 | -} 931 | #+END_SRC 932 | :End: 933 | 934 | Likewise: 935 | #+BEGIN_SRC haskell 936 | [Map ] fmap f p = do {x ← p; pure (f x)} -- By applicative laws 937 | [Join] join ps = do {p ← ps; p} -- By functor laws 938 | #+END_SRC 939 | 940 | *Do-Notation Laws*: Here are some desirable usability properties of ~do~-notation. 941 | #+BEGIN_SRC haskell 942 | [RightIdentity] do {B; x ← p; pure x} = do {B; p} 943 | [LeftIdentity ] do {B; x ← pure e; C; r} = do {B; C[x ≔ e]; r[x ≔ e]} 944 | [Associtivity ] do {B; x ← do {C; p}; D; r} = do {B; C; x ← p; D; r} 945 | #+END_SRC 946 | 947 | Here, ~B, C, D~ range over sequences of commands and ~C[x ≔ e]~ means the sequence ~C~ 948 | with all free occruences of ~x~ replaced by ~e~. 949 | 950 | + Associtivity gives us a nice way to ‘inline’ other calls. 951 | + The LeftIdentity law, read right-to-left, lets us “locally give a name” to the 952 | possibly complex expression ~e~. 953 | 954 | If ~pure~ forms a singleton collection, then LeftIdentity is a “one-point rule”: 955 | We consider /all/ ~x ← pure e~, but there is only /one/ such ~x~, namely ~e~! 956 | # - In list notation: ~[g x | x <- pure e] = [g e]~. 957 | 958 | In the applicative case, where the clauses are independent, we can prove, say, 959 | ~RightIdentity~ using the identity law for applicatives ---which says essentially 960 | {{{newline}}} 961 | ~do {x <- p; pure x} = p~--- then apply induction on the length of ~B~. 962 | 963 | :Hide: 964 | #+BEGIN_SRC haskell 965 | -- applicative laws 966 | [Homomorphism] do {x <- pure e; pure (f x)} = pure (f e) 967 | #+END_SRC 968 | :End: 969 | 970 | What axioms are needed for the monad case to prove the ~do~-notation laws? 971 | 972 | * Monad Laws 973 | # ---“the programmable semicolon”* 974 | 975 | Here is the definition of the monad typeclass. 976 | #+BEGIN_SRC haskell :tangle del_4.hs 977 | class Applicative m => Monad (m :: * -> *) where 978 | (>>=) :: m a -> (a -> m b) -> m b 979 | 980 | (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c 981 | f <=< g = join . fmap f . g 982 | #+END_SRC 983 | 984 | Where's ~join~!? Historically, monads entered Haskell first with interface ~(>>=), 985 | return~; later it was realised that ~return = pure~ and the relationship with 986 | applicative was cemented. 987 | 988 | ‘Bind’ ~(>>=)~ is definable from ~join~ by ~ma >>= f = join (fmap f ma)~, and, for 989 | this reason, bind is known as “flat map” or “concat map” in particular 990 | instances. For instance, the second definition of ~do~-notation could be 991 | expressed: 992 | #+BEGIN_SRC haskell 993 | (2M′) do {x ← p; C; r} = p >>= q where q x = do {C; r} 994 | #+END_SRC 995 | Conversely, ~join ps = do {p ← ps; p} = ps >>= id~. Likewise, with (2M′), note how 996 | ~(<*>)~ can be defined directly in-terms of ~(>>=)~ 997 | {{{newline}}} 998 | ---c.f., ~mf <*> mx = do {f ← mf; 999 | x ← mx; return (f x)}~. 1000 | 1001 | Since ~fmap f p = do {x ← p; return (f x)} = p >>= return . f~, in the past monad 1002 | did not even have functor as a superclass ---c.f., [[http://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Monad.html#v:liftM][liftM]]. 1003 | 1004 | :FlipBind: 1005 | 1006 | (=<<) :: Monad m => (a -> m b) -> m a -> m b 1007 | -- Defined in ‘GHC.Base’ 1008 | infixr 1 =<< 1009 | 1010 | :End: 1011 | 1012 | The properties of ~>>=, return~ that prove the desired ~do~-notation laws are: 1013 | #+BEGIN_SRC haskell 1014 | [LeftIdentity ] return a >>= f ≡ f a 1015 | [RightIdentity] m >>= return ≡ m 1016 | [Associtivity ] (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g) 1017 | i.e., (m >>= (\x -> f x)) >>= g 1018 | = m >>= (\x -> f x >>= g) 1019 | #+END_SRC 1020 | 1021 | Equivalently, show the ‘fish’ ~(<=<)~ is associative with identity being ~pure~ 1022 | ---c.f., monoids! 1023 | 1024 | It is pretty awesome that ~(>>=), return~ give us a functor, an applicative, and 1025 | (dependent) do-notation! Why? Because bind does both the work of ~fmap~ and ~join~. 1026 | Thus, ~pure, fmap, join~ suffice to characterise a monad. 1027 | 1028 | | /Join determines how a monad behaves!/ | 1029 | 1030 | The monad laws can be expressed in terms of ~join~ [[https://en.wikibooks.org/wiki/Haskell/Category_theory#The_monad_laws_and_their_importance][directly]]: 1031 | #+BEGIN_SRC haskell 1032 | [Associativity] join . fmap join = join . join 1033 | {- The only two ways to get from “m (m (m α))” to “m α” are the same. -} 1034 | 1035 | [Identity Laws] join. fmap pure = join . pure = id 1036 | {- Wrapping up “m α” gives an “m (m α)” which flattens to the original element. -} 1037 | #+END_SRC 1038 | # # - The left-hand side will flatten the inner two layers into a new layer, 1039 | # # - then flatten this with the outermost layer. The right-hand side will 1040 | # # - flatten the outer two layers, then flatten this with the innermost 1041 | # # - layer. 1042 | 1043 | Then, notice that the (free) naturality of join is: 1044 | #+BEGIN_SRC haskell 1045 | join . fmap (fmap f) = fmap f . join ∷ m (m α) → m β 1046 | #+END_SRC 1047 | 1048 | # Cool. 1049 | # Notice that ~fmap f p = do { x ← p; pure (f x) } = join $ fmap (pure . f) p~ 1050 | 1051 | Again, note that ~join~ doesn't merely flatten a monad value, but rather performs 1052 | the necessary logic that determines /how the monad behaves/. 1053 | # Indeed, ~join, pure, fmap~ suffice to characterise a monad. 1054 | 1055 | E.g., suppose ~m α = ε → (ε, α)~ is the type of ~α~-values that can be configured 1056 | according to a fixed environment type ~ε~, along with the possibly updated 1057 | configuration ---i.e., functions ~ε → (ε, α)~. Then any ~a ∶ ε → (ε, ε → (ε, α))~ in ~m 1058 | (m α)~ can be considered an element of ~m α~ if we /propagate the environment 1059 | configuration/ through the outer layer to obtain a new configuration for the 1060 | inner layer: ~λ e → let (e′, a′) = a e in a′ e′~. The join dictates how a 1061 | configuration is /modified then passed along/: We have two actions, ~a~ and ~a′~, and 1062 | join has /sequenced/ them by pushing the environment through the first thereby 1063 | modifying it then pushing it through the second. 1064 | 1065 | * Monad Examples 1066 | 1067 | Let ~f₁, f₂~ be functors and let ~ε~ a type. 1068 | 1069 | | Applicative | ~m α~ | ~join :: m (m α) → m α~ | 1070 | |-------------+--------------+-----------------------------------------| 1071 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Identity.html#t:Identity][Identity]] | ~α~ | ~λ x → x~ | 1072 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Applicative.html#t:Const][Constant]] | ~ε~ | ~λ x → x~ ---Shucks! Not a monad! | 1073 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-List.html][List]] | ~[α]~ | ~λ xss → foldr (++) [] xss~ | 1074 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Either.html#t:Either][Either]] | ~Either ε α~ | Exercise ^_^ | 1075 | |-------------+--------------+-----------------------------------------| 1076 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Compose.html#t:Compose][Composition]] | ~f₁ (f₂ α)~ | [[https://stackoverflow.com/q/7040844/3550444][Nope! Not a monad!]] | 1077 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Product.html#t:Product][Product]] | ~(f₁ α, f₂ α)~ | ~λ p → (fst <$> p, snd <$> p)~ | 1078 | |-------------+--------------+-----------------------------------------| 1079 | | [[http://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Writer-Lazy.html#g:2][Writer]] | ~(ε, α)~ | ~λ (e, (e′, a)) → (e <> e′, a)~ | 1080 | | [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Reader.html][Reader]] | ~ε → α~ | ~λ ra → λ e → ra e e~ | 1081 | | [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-State-Lazy.html#g:2][State]] | ~ε → (ε, α)~ | ~λ ra → λ e → let (e′, a) = ra e in a e′~ | 1082 | # # 1083 | # | [[http://comonad.com/reader/2012/abstracting-with-applicatives/][Sum]] | ~Either (f₁ α) (f₂ α)~ | Challenge: Assume ~η ∷ f₁ a → f₂ a~ | 1084 | 1085 | In writer, we need ~ε~ to be a monoid. 1086 | 1087 | + Notice how, in writer, join merges the outer context with the inner context: 1088 | /Sequential writes are mappended together!/ 1089 | + If ~pure~ forms ‘singleton containers’ then ~join~ flattens containers of containers 1090 | into a single container. 1091 | 1092 | Excluding the trivial monoid, the constant functor is /not/ a monad: It fails the 1093 | monad identity laws for join. Similarly, ~f α = Maybe (α, α)~ is an applicative 1094 | but /not/ a monad ---since there is no lawful definition of ~join~. Hence, 1095 | applicatives are strictly more generally than monads. 1096 | :Indeed: 1097 | #+BEGIN_SRC haskell 1098 | id x = join $ fmap pure x 1099 | ≡ x = join $ mempty 1100 | ≡ x = mempty! 1101 | #+END_SRC 1102 | :End: 1103 | 1104 | :Hide: 1105 | #+BEGIN_SRC haskell 1106 | -- Either 1107 | join (Right (Right a)) = Right a 1108 | join (Right (Left e)) = Left e 1109 | join (Left e) = Left e 1110 | 1111 | -- Cont 1112 | join f = \k -> f (\f' -> f' k) 1113 | #+END_SRC 1114 | :End: 1115 | 1116 | * COMMENT Hide - monad laws 1117 | 1118 | #+BEGIN_SRC haskell 1119 | -- join . pure = id 1120 | do {pure p} = p -- ?? 1121 | 1122 | -- join . fmap pure = id 1123 | do {x <- p; pure x} = p -- cf RightIdentity! 1124 | 1125 | -- join . fmap join = join . join 1126 | do {x ← p; do {C; r}} = do {x ← p; C; r} --?? cf Associtivity 1127 | #+END_SRC 1128 | 1129 | * COMMENT Comparing Monad and Applicative 1130 | 1131 | [[http://www.staff.city.ac.uk/~ross/papers/Applicative.pdf][Intuitively]], the ~(>>=) :: m α → (α → m β) → m β~ of a monad ~m~ allows the value 1132 | returned by one computation to influence the choice of another, whereas ~(<*>)~ 1133 | keeps the structure of a computation fixed, just sequencing the effects. For 1134 | example, in ~wx >>= λ x → if x then wy else wz~ the value of ~wx~ will choose between 1135 | the /computations/ ~wy~ and ~wz~, performing only one, whilst ~(λ x y z → if x then y 1136 | else z) <$> wx <*> wy <*> wz~ performs the effects of all three computations, 1137 | using the value of ~wx~ to choose only between the /values/ of ~wy~ and ~wz~. For 1138 | example, if ~f α = m α = [α]~ and ~wx = [True], wz = []~ then the applicative 1139 | expression is ~[]~ since the ‘else’ computation ‘fails’, whereas the monadic 1140 | expression is ~wy~. [[http://www.staff.city.ac.uk/~ross/papers/Applicative.pdf][However]], whereas monads abort on the first ‘failure’, /with the 1141 | applicative interface we can continue in the face of errors./ 1142 | #+BEGIN_SRC haskell 1143 | f :: Applicative f => f Bool -> f b -> f b -> f b 1144 | f xs ys zs = (\x y z -> if x then y else z) <$> xs <*> ys <*> zs 1145 | 1146 | > f [True] [1..10] [] 1147 | [] 1148 | 1149 | m xs ys zs = xs >>= \x -> if x then ys else zs 1150 | 1151 | > m [True] [1..10] [] 1152 | [1,2,3,4,5,6,7,8,9,10] 1153 | #+END_SRC 1154 | 1155 | Hence, properties of applicatives ---such as length--- can be determined 1156 | statically just by looking at the inputs, whereas monadic expressions can change 1157 | the collection structure ---and its properties--- since they can look at 1158 | intermediate results to decide what to do next. 1159 | 1160 | Applicatives sequence independent effects, whereas monads allow effects to 1161 | depend on each other. 1162 | 1163 | * Running Example ---A Simple Arithmetic Language 1164 | 1165 | Let's start with a weak language: 1166 | #+BEGIN_SRC haskell :tangle simple_terms.hs 1167 | data Term = Int Int | Div Term Term deriving Show 1168 | 1169 | thirteen = Int 1729 `Div` (Int 133 `Div` Int 1) 1170 | boom = Int 1729 `Div` (Int 12 `Div` Int 0) 1171 | 1172 | eval₀ :: Term -> Int 1173 | eval₀ (Int n) = n 1174 | eval₀ (n `Div` d) = let top = eval₀ n 1175 | bottom = eval₀ d 1176 | in top `div` bottom 1177 | #+END_SRC 1178 | 1179 | How do we accomodate safe division by zero? Print to the user what's happening 1180 | at each step of the calcuation? Have terms that access ‘global’ variables? Have 1181 | terms that can store named expressions then access them later? 1182 | 1183 | We'll make such languages and their ~eval~'s will be nearly just as simple as this 1184 | one (!) but accomodate these other issues. 1185 | 1186 | * [[http://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Maybe.html][Maybe]] ---Possibly Failing Computations 1187 | Safe evaluator: No division errors. 1188 | #+BEGIN_SRC haskell :tangle simple_terms.hs 1189 | eval₁ :: Term -> Maybe Int 1190 | eval₁ (Int n) = pure n 1191 | eval₁ (n `Div` d) = do t <- eval₁ n 1192 | b <- eval₁ d 1193 | if b == 0 then Nothing else pure (t `div` b) 1194 | #+END_SRC 1195 | Exercise: Rewrite ~evalᵢ~ without ~do~-notation and you'll end-up with nested case 1196 | analysis leading into a straicase of code that runs right off the page. 1197 | 1198 | - Applicative is enough for ~eval₁, eval₂, eval₃~, but ~eval₄~ needs ~Monad~. 1199 | 1200 | * [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Writer-Lazy.html#g:2][Writer]] ---Logging Information as we Compute 1201 | 1202 | Use a pair type ~W ε α~ to keep track of an environment ~ε~ and a value ~α~. 1203 | #+BEGIN_SRC haskell :tangle simple_terms.hs 1204 | data Writer ε α = W ε α deriving Show 1205 | 1206 | write :: ε -> Writer ε () 1207 | write e = W e () 1208 | 1209 | instance Functor (Writer ε) where 1210 | fmap f (W e a) = W e (f a) 1211 | #+END_SRC 1212 | Aggregate, merge, environments using their monoidal operation. 1213 | #+BEGIN_SRC haskell :tangle simple_terms.hs 1214 | instance Monoid ε => Applicative (Writer ε) where 1215 | pure a = W mempty a 1216 | (W e f) <*> (W d a) = W (e <> d) (f a) 1217 | 1218 | instance Monoid ε => Monad (Writer ε) where 1219 | (>>=) = \ ma f -> join (pure f <*> ma) 1220 | where join (W e (W d a)) = W (e <> d) a 1221 | #+END_SRC 1222 | 1223 | An evaluator that prints to the user what's going on. 1224 | #+BEGIN_SRC haskell :tangle simple_terms.hs 1225 | eval₂ :: Term -> Writer String Int 1226 | eval₂ it@(Int n) = W ("\n Evaluating: " ++ show it) n 1227 | eval₂ it@(n `Div` d) = do write $ "\n Evaluating: " ++ show it 1228 | t <- eval₂ n 1229 | b <- eval₂ d 1230 | pure $ (t `div` b) 1231 | 1232 | -- Try this! With “boom”, we get to see up to the boint of the error ^_^ 1233 | -- let W e x = eval₂ thirteen in putStrLn e 1234 | #+END_SRC 1235 | 1236 | * spacing break :ignore: 1237 | #+latex: \vspace{-1em} 1238 | * [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Reader.html#g:2][Reader]] ---Accessing ‘Global, read-only, data’ 1239 | # Reader let's us simulate “global, read-only, data”. 1240 | 1241 | #+latex: \hspace{-1.5em} 1242 | Use a function type ~ε → α~ to get ~α~-values that ‘reads’ from a configuration 1243 | environment ε. 1244 | #+BEGIN_SRC haskell :tangle terms_with_vars.hs 1245 | data Reader ε α = R {run :: ε -> α} 1246 | 1247 | instance Functor (Reader ε) where 1248 | fmap f (R g) = R $ f . g 1249 | 1250 | instance Applicative (Reader ε) where 1251 | pure a = R $ const a 1252 | (R f) <*> (R g) = R $ \e -> f e (g e) {- “S” combinator -} 1253 | 1254 | instance Monad (Reader ε) where 1255 | ma >>= f = join (pure f <*> ma) 1256 | where join (R rf) = R $ \e -> run (rf e) e 1257 | #+END_SRC 1258 | 1259 | A language with access to global variables; uninitialised variables are 0 by 1260 | default. 1261 | #+BEGIN_SRC haskell :tangle terms_with_vars.hs 1262 | data Term = Int Int | Div Term Term | Var String deriving Show 1263 | 1264 | type GlobalVars = [(String, Int)] 1265 | 1266 | valuefrom :: String -> GlobalVars -> Int 1267 | valuefrom x gvs = maybe 0 id $ lookup x gvs 1268 | 1269 | eval₃ :: Term -> Reader GlobalVars Int 1270 | eval₃ (Int x) = pure x 1271 | eval₃ (Var x) = R $ \e -> x `valuefrom` e 1272 | eval₃ (n `Div` d) = do t <- eval₃ n 1273 | b <- eval₃ d 1274 | pure (t `div` b) 1275 | 1276 | state = [("x", 1729), ("y", 133)] :: GlobalVars 1277 | thirteen = Var "x" `Div` (Var "y" `Div` Int 1) 1278 | -- run (eval₃ thirteen) state 1279 | #+END_SRC 1280 | 1281 | * [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-State-Lazy.html#g:2][State]] ---Read and write to local storage 1282 | 1283 | Let's combine writer and reader to get state: We can both read and write to data 1284 | by using functions ~ε → (ε, α)~ that read from an environment ε and result in a 1285 | new environment as well as a value. 1286 | - ~IO α ≅ State TheRealWorld α~ ;-) 1287 | #+BEGIN_SRC haskell :tangle terms_with_storage.hs 1288 | data State ε α = S {run :: ε -> (ε, α)} 1289 | 1290 | push :: Monoid ε => ε -> State ε () 1291 | push d = S $ \e -> (d <> e, ()) 1292 | 1293 | instance Functor (State ε) where 1294 | fmap f (S g) = S $ \ e -> let (e', a) = g e in (e', f a) 1295 | 1296 | instance Applicative (State ε) where 1297 | pure a = S $ \e -> (e, a) 1298 | (S sf) <*> (S g) = S $ \e -> let (e', a) = g e 1299 | (e'', f) = sf e' in (e'', f a) 1300 | 1301 | instance Monad (State ε) where 1302 | ma >>= f = join (pure f <*> ma) 1303 | where join (S sf) = S $ \e -> let (e', S f) = sf e in f e' 1304 | #+END_SRC 1305 | 1306 | A simple language with storage; a program's value is the value of its final store. 1307 | :Repeated: 1308 | #+BEGIN_SRC haskell :tangle terms_with_storage.hs 1309 | type GlobalVars = [(String, Int)] 1310 | 1311 | valuefrom :: String -> GlobalVars -> Int 1312 | valuefrom x gvs = maybe 0 id $ lookup x gvs 1313 | #+END_SRC 1314 | :End: 1315 | 1316 | #+BEGIN_SRC haskell :tangle terms_with_storage.hs 1317 | data Expr = Let String Expr Expr | Var String | Int Int | Div Expr Expr 1318 | deriving Show 1319 | 1320 | eval₄ :: Expr -> State GlobalVars Int 1321 | eval₄ (Var x) = S $ \e -> let r = x `valuefrom` e in ((x,r):e, r) 1322 | eval₄ (Int x) = pure x 1323 | eval₄ (Let x t body) = do n <- eval₄ t 1324 | push [(x, n)] -- Applicative is NOT enough here! 1325 | eval₄ body 1326 | eval₄ (n `Div` d) = do t <- eval₄ n; b <- eval₄ d; pure (t `div` b) 1327 | 1328 | thirteen = Let "x" (Int 1729) 1329 | $ Let "y" (Int 133 `Div` Int 1) 1330 | $ Var "x" `Div` Var "y" 1331 | 1332 | -- run (eval₄ thirteen) [] 1333 | #+END_SRC 1334 | 1335 | Exercise: Add to the oringal =Term= type a constructor =Rndm [Term]=, where =Rndm 1336 | [t₁, …, tₙ]= denotes non-deterministicly choosing one of the terms ~tᵢ~. Then write 1337 | an evaluator that considers all possible branches of a computation: 1338 | ~eval₅ : Term → [Int]~. 1339 | 1340 | If we want to mixin any of the features for our evaluators, we need to use ‘monad 1341 | transformers’ since monads do not compose in general. 1342 | 1343 | * spacing break :ignore: 1344 | #+latex: \columnbreak 1345 | * Reads 1346 | 1347 | + /Introduction to Functional Programming/ by Richard Bird 1348 | - Assuming no programming, this book end by showing how to write a theorem 1349 | prover powerful enough to prove many of laws scattered throughout the book. 1350 | 1351 | + [[http://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf][Monads for functional programming]] by Philip Wadler 1352 | - This covers the ~evalᵢ~ and more ^_^ 1353 | 1354 | + [[https://docs.racket-lang.org/heresy/monad-do.html][Comprehending Monads]] by Philip Wadler 1355 | 1356 | + [[http://dev.stephendiehl.com/hask/][What I Wish I Knew When Learning Haskell]] 1357 | 1358 | + [[https://wiki.haskell.org/Typeclassopedia][Typeclassopedia]] ---/The essentials of each type class are introduced, with 1359 | examples, commentary, and extensive references for further reading./ 1360 | 1361 | + [[http://blog.sigfpe.com/2006/08/you-could-have-invented-monads-and.html][You Could Have Invented Monads! (And Maybe You Already Have.)]] 1362 | 1363 | + [[http://learnyouahaskell.com/chapters][Learn You a Haskell for Great Good]] ---An accessible read with many examples, and drawings 1364 | 1365 | + [[https://en.wikibooks.org/wiki/Haskell][The Haskell WikiBook]] ---Has four beginner's tracks and four advanced tracks 1366 | 1367 | + [[https://alhassy.github.io/CatsCheatSheet/CheatSheet.pdf][Category Theory Cheat Sheet]] ---The “theory of typed composition”: 1368 | Products, Sums, Functors, Natural Transformations ^_^ 1369 | 1370 | + [[https://alhassy.github.io/AgdaCheatSheet/CheatSheet.pdf][Agda Cheat Sheet]] ---Agda is Haskell on steroids in that it you can invoke 1371 | Haskell code and write proofs for it. 1372 | 1373 | + LINQ for [[http://tomasp.net/blog/idioms-in-linq.aspx/#csidiomsl][applicatives]] and [[https://livebook.manning.com/book/real-world-functional-programming/chapter-12/28][monads]]. 1374 | - Monads ≈ SQL/Linq ≈ Comprehensions/Generators 1375 | 1376 | :TODO: 1377 | http://homepages.inf.ed.ac.uk/wadler/topics/links.html#arrows-and-idioms 1378 | How arrows fit into the functor/applicative/monad hierarchy? See Idioms are 1379 | oblivious, arrows are meticulous, monads are promiscuous by Sam Lindley, Philip 1380 | Wadler, Jeremy Yallop. MSFP 2008. (They call applicative functors idioms.) The 1381 | abstract: 1382 | 1383 | We revisit the connection between three notions of computation: Moggi's monads, 1384 | Hughes's arrows and McBride and Paterson's idioms (also called applicative 1385 | functors). We show that idioms are equivalent to arrows that satisfy the type 1386 | isomorphism A ~> B = 1 ~> (A -> B) and that monads are equivalent to arrows that 1387 | satisfy the type isomorphism A ~> B = A -> (1 ~> B). Further, idioms embed into 1388 | arrows and arrows embed into monads. 1389 | :END: 1390 | 1391 | * COMMENT What if I want ~N~ columns? Or non-landscape? Or multiple formats? 1392 | 1393 | Press ~C-c C-c~ on the following incantation to produce a single column portrait of the cheat sheet. 1394 | #+name: make-portrait 1395 | #+BEGIN_SRC emacs-lisp :results none 1396 | (with-temp-buffer 1397 | (insert 1398 | "#+EXPORT_FILE_NAME: CheatSheet_Portrait.pdf 1399 | ,#+LATEX_HEADER_EXTRA: \\landscapefalse \\def\\cheatsheetcols{1} 1400 | ,#+INCLUDE: CheatSheet.org 1401 | ") 1402 | 1403 | (let ((org-export-use-babel nil)) 1404 | (org-mode) 1405 | (org-latex-export-to-pdf) 1406 | ) 1407 | ) 1408 | #+END_SRC 1409 | 1410 | * COMMENT Basic Equational Support 1411 | 1412 | # Basic name-formula equational support. 1413 | 1414 | ~\eqn{name}{formula}~ 1415 | yields a displayed equation with ~formula~ left aligned and ~name~ right aligned: 1416 | 1417 | #+latex: \vspace{-0.7em} 1418 | \eqn{name}{formula} 1419 | #+BEGIN_EXPORT latex 1420 | \eqn{Functoriality}{ 1421 | F(f_0 \circ \cdots \circ f_{n-1}) \;=\; F\, f_0 \circ \cdots \circ F\, f_{n-1} 1422 | } 1423 | #+END_EXPORT 1424 | 1425 | Moreover, we can refer to such a formula by invoking ~\ref{name}~ ---e.g., \ref{Functoriality} and \ref{name}. 1426 | However, if ~name~ involves unicode symbols, then this may cause problems. 1427 | 1428 | See the [[https://github.com/alhassy/CatsCheatSheet][CatsCheatSheet]] for examples of this kind. 1429 | 1430 | We may also use [[https://github.com/jkitchin/org-ref][org-ref]] style references, as in ~eqref:name~. However, org-ref may warn that 1431 | no context for the reference is found ---that's okay. 1432 | 1433 | + eqref :: Parenthesised reference: eqref:name 1434 | + autoref :: Prefix reference with type: autoref:name 1435 | + nameref :: The name of the section that contains this reference: nameref:name 1436 | 1437 | :MultipleEquationsExample: 1438 | 1439 | preamble words here --below comes from CatsCheatSheet-- 1440 | 1441 | #+BEGIN_EXPORT latex 1442 | \begineqns 1443 | 1444 | \eqn{$\langle\rangle$-Type}{f : C → A \lands g : C → B \impliesS ⟨f, g⟩ : C → A × B} 1445 | 1446 | \eqn{$\langle\rangle$-Char}{ \fst ∘ x = f \lands \snd ∘ x = g \equivS x = ⟨f, g⟩ } 1447 | 1448 | \eqn{$\langle\rangle$-Cancellation; $\langle\rangle$-Self}{ \fst ∘ ⟨f, g⟩ = f \landS \snd ∘ ⟨f, g⟩ = g} 1449 | 1450 | \eqn{$\langle\rangle$-Id}{ ⟨\fst, \snd⟩ = \Id} 1451 | 1452 | \eqn{$\langle\rangle$-Unique}{ \fst ∘ x = \fst ∘ y \lands \snd ∘ x = \snd ∘ y \impliesS x = y} 1453 | 1454 | \eqn{$\langle\rangle$-Fusion}{ ⟨f , g⟩ ∘ x = ⟨f ∘ x , g ∘ x⟩ } 1455 | 1456 | \eqn{$\langle\rangle$-Functor-Dist}{F \, ⟨f, g⟩_𝒞 = ⟨F \, f , F \, g⟩_𝒟 \qquad\text{ where } F : 𝒞 → 𝒟} 1457 | 1458 | \endeqns 1459 | #+END_EXPORT 1460 | 1461 | #+latex: \room 1462 | #+latex: \room 1463 | 1464 | postamble words here 1465 | 1466 | :End: 1467 | 1468 | #+latex: \vspace{-3em} 1469 | * COMMENT Parallel Environment 1470 | 1471 | Cheat sheets should not waste space, so the setup provides 1472 | a ~parallel~ LaTeX enviornment that takes an optional parameter 1473 | indicating how many columns are desired ---two by default. 1474 | Importantly, we use this environment as if it were any normal org-block: 1475 | # 1476 | #+begin_parallel org 1477 | #+BEGIN_EXAMPLE org :tangle no 1478 | ,#⸲ 1479 | ,#+begin_parallel org 1480 | ???content here??? 1481 | ,#+end_parallel 1482 | #+END_EXAMPLE 1483 | 1484 | The initial new line is important, otherwise the parallel environment 1485 | occurs in-line, which may not be the intended behaviour. 1486 | #+end_parallel 1487 | 1488 | The column break is automatic, but as 1489 | this is sugar for a ~minipage~ containing a ~multicolum~ we can force a column 1490 | separation with ~\columnbreak~. 1491 | # This command, in Org, necessities newlines between 1492 | # the items being separated. 1493 | 1494 | ~parallelNB~ produces a side-by-side rendition with ‘N’o ‘B’ar: 1495 | # 1496 | #+begin_parallelNB org 1497 | left \newline left \newline left 1498 | 1499 | #+latex: \columnbreak 1500 | right \newline right \newline right 1501 | #+end_parallelNB 1502 | 1503 | Here is an example with four columns: 1504 | # 1505 | #+ATTR_LATEX: :options [4] 1506 | #+begin_parallel org 1507 | left \newline left \newline left 1508 | 1509 | #+latex: \columnbreak 1510 | middle \newline middle \newline middle 1511 | 1512 | #+latex: \columnbreak 1513 | middle \newline middle \newline middle 1514 | 1515 | #+latex: \columnbreak 1516 | right \newline right \newline right 1517 | #+end_parallel 1518 | 1519 | Here is an example with three columns and ‘n’o ‘b’ar: 1520 | # 1521 | #+begin_parallel3NB org 1522 | left \newline left \newline left 1523 | 1524 | #+latex: \columnbreak 1525 | middle \newline middle \newline middle 1526 | 1527 | #+latex: \columnbreak 1528 | right \newline right \newline right 1529 | #+end_parallel3NB 1530 | 1531 | #+latex: \vfill {\color{white}.} 1532 | 1533 | * spacing COMMENT break :accomodating_multiple_formats:ignore: 1534 | 1535 | #+LATEX: \ifnum\cheatsheetcols=1 \newpage \else \columnbreak \fi 1536 | 1537 | * COMMENT Making ~README.org~ 1538 | 1539 | Evaluate the following source block with ~C-c C-c~ 1540 | to produce a ~README~ file. 1541 | 1542 | # :'( For some reason using {{{title}}} below would not work. 1543 | 1544 | #+NAME: make-readme 1545 | #+BEGIN_SRC emacs-lisp 1546 | (with-temp-buffer 1547 | (insert 1548 | "#+EXPORT_FILE_NAME: README.org 1549 | # HTML:
1577 |
1578 | ,#+TOC: headlines 2
1579 | ,#+INCLUDE: CheatSheet.org
1580 | ")
1581 |
1582 | ;; No code execution on export
1583 | ;; ⟪ For a particular block, we use “:eval never-export” ⟫
1584 | ;;
1585 | (let ((org-export-use-babel nil))
1586 | (org-mode)
1587 | ; (org-md-export-to-markdown)
1588 | ; (package-install 'toc-org)
1589 | (toc-org-mode)
1590 | (toc-org-insert-toc)
1591 | (org-org-export-to-org)
1592 | )
1593 | )
1594 | #+END_SRC
1595 |
1596 |
1597 | Note that the ~blurb~ macro is defined by the user, to provide a terse description of the project.
1598 | - Think the one-line statement at the top of a github repo page.
1599 |
1600 | # The ~d:nil~ ensures the ‘drawer’ ~:Hide: ⋯ :End:~ is not exported; it's there for me
1601 | # as a reminder.
1602 |
--------------------------------------------------------------------------------
/CheatSheet.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alhassy/HaskellCheatSheet/943ba07b46251485ae415d7c78b9edd02e284d7d/CheatSheet.pdf
--------------------------------------------------------------------------------
/CheatSheet_Portrait.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alhassy/HaskellCheatSheet/943ba07b46251485ae415d7c78b9edd02e284d7d/CheatSheet_Portrait.pdf
--------------------------------------------------------------------------------
/README.org:
--------------------------------------------------------------------------------
1 | # Created 2020-04-04 Sat 22:32
2 | #+OPTIONS: toc:nil d:nil
3 | #+OPTIONS: toc:nil d:nil
4 | #+TITLE: Haskell CheatSheet
5 | #+AUTHOR: [[https://alhassy.github.io/][Musa Al-hassy]]
6 | #+export_file_name: README.org
7 |
8 | A reference sheet for the basics of the mind-expanding Haskell language (•̀ᴗ•́)و
9 |
10 | #+begin_quote
11 | *The listing sheet, as PDF, can be found
12 | [[https://alhassy.github.io/HaskellCheatSheet/CheatSheet.pdf][here]]*,
13 | or as a [[https://alhassy.github.io/HaskellCheatSheet/CheatSheet_Portrait.pdf][single column portrait]],
14 | while below is an unruly html rendition.
15 | #+end_quote
16 |
17 | This reference sheet is built from a
18 | [[https://github.com/alhassy/CheatSheet][CheatSheets with Org-mode]]
19 | system.
20 |
21 | #+html:
22 |
23 | #+toc: headlines 2
24 | #+macro: blurb A reference sheet for the basics of the mind-expanding Haskell language (•̀ᴗ•́)و
25 |
26 | #+latex_header: \usepackage{titling,parskip}
27 | #+latex_header: \usepackage{eufrak} % for mathfrak fonts
28 | #+latex_header: \usepackage{multicol,xparse,newunicodechar}
29 |
30 | #+latex_header: \usepackage{etoolbox}
31 |
32 | #+latex_header: \newif\iflandscape
33 | #+latex_header: \landscapetrue
34 |
35 | #+latex_header_extra: \iflandscape \usepackage[landscape, margin=0.5in]{geometry} \else \usepackage[margin=0.5in]{geometry} \fi
36 |
37 | #+latex_header: \def\cheatsheetcols{2}
38 | #+latex_header: \AfterEndPreamble{\begin{multicols}{\cheatsheetcols}}
39 | #+latex_header: \AtEndDocument{ \end{multicols} }
40 |
41 | #+latex_header: \let\multicolmulticols\multicols
42 | #+latex_header: \let\endmulticolmulticols\endmulticols
43 | #+latex_header: \RenewDocumentEnvironment{multicols}{mO{}}{\ifnum#1=1 #2 \def\columnbreak{} \else \multicolmulticols{#1}[#2] \fi}{\ifnum#1=1 \else \endmulticolmulticols\fi}
44 |
45 | #+latex_header: \def\maketitle{}
46 | #+latex: \fontsize{9}{10}\selectfont
47 |
48 | #+latex_header: \def\cheatsheeturl{}
49 |
50 | #+latex_header: \usepackage[dvipsnames]{xcolor} % named colours
51 | #+latex: \definecolor{grey}{rgb}{0.5,0.5,0.5}
52 |
53 | #+latex_header: \usepackage{color}
54 | #+latex_header: \definecolor{darkgreen}{rgb}{0.0, 0.3, 0.1}
55 | #+latex_header: \definecolor{darkblue}{rgb}{0.0, 0.1, 0.3}
56 | #+latex_header: \hypersetup{colorlinks,linkcolor=darkblue,citecolor=darkblue,urlcolor=darkgreen}
57 |
58 | #+latex_header: \setlength{\parindent}{0pt}
59 |
60 |
61 | #+latex_header: \def\cheatsheetitemsep{-0.5em}
62 | #+latex_header: \let\olditem\item
63 | #+latex_header_extra: \def\item{\vspace{\cheatsheetitemsep}\olditem}
64 |
65 | #+latex_header: \usepackage{CheatSheet/UnicodeSymbols}
66 |
67 | #+latex_header: \makeatletter
68 | #+latex_header: \AtBeginEnvironment{minted}{\dontdofcolorbox}
69 | #+latex_header: \def\dontdofcolorbox{\renewcommand\fcolorbox[4][]{##4}}
70 | #+latex_header: \makeatother
71 |
72 |
73 |
74 | #+latex_header: \RequirePackage{fancyvrb}
75 | #+latex_header: \DefineVerbatimEnvironment{verbatim}{Verbatim}{fontsize=\scriptsize}
76 |
77 |
78 | #+macro: newline @@latex: \newline@@
79 |
80 | #+latex_header: \def\cheatsheeturl{https://github.com/alhassy/HaskellCheatSheet}
81 |
82 | #+latex_header: \def\cheatsheetcols{2}
83 | #+latex_header: \landscapetrue
84 | #+latex_header: \def\cheatsheetitemsep{-0.5em}
85 |
86 | #+latex_header: \newunicodechar{𝑻}{\ensuremath{T}}
87 | #+latex_header: \newunicodechar{⊕}{\ensuremath{\oplus}}
88 | #+latex_header: \newunicodechar{≈}{\ensuremath{\approx}}
89 | #+latex_header: \newunicodechar{𝓍}{\ensuremath{x}}
90 | #+latex_header: \newunicodechar{α}{\ensuremath{\alpha}}
91 | #+latex_header: \newunicodechar{β}{\ensuremath{\beta}}
92 | #+latex_header: \newunicodechar{ε}{\ensuremath{\epsilon}}
93 | #+latex_header: \newunicodechar{∂}{\ensuremath{\partial}}
94 | #+latex_header: \newunicodechar{⊝}{\ensuremath{\ominus}}
95 | #+latex_header: \newunicodechar{₋}{\ensuremath{_-}}
96 | #+latex_header: \newunicodechar{⟶}{\ensuremath{\rightarrow}}
97 | #+latex_header: \newunicodechar{∉}{\ensuremath{\not\in}}
98 | #+latex_header: \newunicodechar{ }{\ensuremath{\;\;}}
99 |
100 | #+begin_quote
101 | - [[#hello-home][Hello, Home!]]
102 | - [[#pattern-matching][Pattern Matching]]
103 | - [[#local-bindings][Local Bindings]]
104 | - [[#operators][Operators]]
105 | - [[#types][Types]]
106 | - [[#tuples][Tuples]]
107 | - [[#lists][Lists]]
108 | - [[#pattern-matching-on-lists][Pattern Matching on Lists]]
109 | - [[#common-methods-on-lists][Common Methods on Lists]]
110 | - [[#list-design-patterns][List ‘Design Patterns’]]
111 | - [[#map][Map]]
112 | - [[#filter][Filter]]
113 | - [[#fold][Fold]]
114 | - [[#algebraic-data-types][Algebraic data types]]
115 | - [[#typeclasses-and-overloading][Typeclasses and overloading]]
116 | - [[#functor][Functor]]
117 | - [[#identity-axiom][Identity Axiom]]
118 | - [[#fusion-axiom][Fusion Axiom]]
119 | - [[#functors-do-not-necessarily-contain-anything][Functors do not necessarily ‘contain’ anything]]
120 | - [[#misc-results-about-functors][Misc results about Functors]]
121 | - [[#functor-examples][Functor Examples]]
122 | - [[#applicative][Applicative]]
123 | - [[#axioms][Axioms]]
124 | - [[#canonical-form----liftn][Canonical Form -- =liftN=]]
125 | - [[#monoidal-presentation][Monoidal Presentation]]
126 | - [[#applicative-examples][Applicative Examples]]
127 | - [[#do-notation----subtle-difference-between-applicatives-and-monads][~Do~-Notation ---Subtle difference between applicatives and monads]]
128 | - [[#do-notation-with-tuples-and-functions][Do-notation with tuples and functions]]
129 | - [[#formal-definition-of-do-notation][Formal Definition of ~Do~-Notation]]
130 | - [[#monad-laws][Monad Laws]]
131 | - [[#monad-examples][Monad Examples]]
132 | - [[#running-example----a-simple-arithmetic-language][Running Example ---A Simple Arithmetic Language]]
133 | - [[#maybe----possibly-failing-computations][Maybe ---Possibly Failing Computations]]
134 | - [[#writer----logging-information-as-we-compute][Writer ---Logging Information as we Compute]]
135 | - [[#reader----accessing-global-read-only-data][Reader ---Accessing ‘Global, read-only, data’]]
136 | - [[#state----read-and-write-to-local-storage][State ---Read and write to local storage]]
137 | - [[#reads][Reads]]
138 | #+end_quote
139 |
140 | * Hello, Home!
141 |
142 | #+begin_src haskell :tangle home.hs
143 | main = do putStr "What's your name? "
144 | name <- getLine
145 | putStrLn ("It's 2020, " ++ name ++ "! Stay home, stay safe!")
146 | #+end_src
147 |
148 | * Pattern Matching
149 |
150 | Functions can be defined using the usual ~if_then_else_~ construct, or
151 | as expressions /guarded/ by Boolean expressions as in mathematics, or
152 | by /pattern matching/ ---a form of ‘syntactic comparision’.
153 |
154 | #+begin_src haskell
155 | fact n = if n == 0 then 1 else n * fact (n - 1)
156 |
157 | fact' n | n == 0 = 1
158 | | n != 0 = n * fact' (n - 1)
159 |
160 | fact'' 0 = 1
161 | fact'' n = n * fact'' (n - 1)
162 | #+end_src
163 |
164 | The above definitions of the factorial function are all equal.
165 |
166 | Guards, as in the second version, are a form of ‘multi-branching conditional’.
167 |
168 | In the final version, when a call, say, ~fact 5~ happens we compare
169 | /syntactically/ whether ~5~ and the first pattern ~0~ are the same. They are not,
170 | so we consider the second case with the understanding that an identifier
171 | appearing in a pattern matches /any/ argument, so the second clause is used.
172 |
173 | Hence, when pattern matching is used, order of equations matters: If we
174 | declared the ~n~-pattern first, then the call ~fact 0~ would match it and we end
175 | up with ~0 * fact (-1)~, which is not what we want!
176 |
177 | If we simply defined the final ~fact~ using /only/ the first clause, then
178 | ~fact 1~ would crash with the error /Non-exhaustive patterns in function fact/.
179 | That is, we may define /partial functions/ by not considering all possible shapes of
180 | inputs.
181 |
182 | See also [[https://gitlab.haskell.org/ghc/ghc/-/wikis/view-patterns][“view patterns”]].
183 |
184 | * Local Bindings
185 |
186 | An equation can be qualified by a ~where~ or ~let~ clause for defining values or
187 | functions used only within an expression.
188 |
189 | #+begin_src haskell
190 | …e…e…e where e = ℯ𝓍𝓅𝓇
191 | ≈ let e = ℯ𝓍𝓅𝓇 in …ℯ𝓍𝓅𝓇…ℯ𝓍𝓅𝓇…ℯ𝓍𝓅𝓇
192 | #+end_src
193 |
194 | It sometimes happens in functional programs that one clause of a function needs
195 | /part of/ an argument, while another operators on the /whole/ argument. It it
196 | tedious (and inefficient) to write out the structure of the complete argument
197 | again when referring to it.
198 | Use the “as operator” ~@~ to label all or part of an argument, as in
199 |
200 | #+begin_src haskell
201 | f label@(x:y:ys) = ⋯
202 | #+end_src
203 |
204 | * Operators
205 | Infix operators in Haskell must consist entiry of ‘symbols’ such as ~&, ^, !, …~
206 | rather than alphanumeric characters. Hence, while addition, ~+~, is written infix,
207 | integer division is written prefix with ~div~.
208 |
209 | We can always use whatever fixity we like:
210 | - If ~f~ is any /prefix/ binary function, then ~x `f` y~ is a valid /infix/ call.
211 | - If ~⊕~ is any /infix/ binary operator, then ~(⊕) x y~ is a valid /prefix/ call.
212 |
213 | It is common to fix one argument ahead of time, e.g., ~λ x → x + 1~ is the
214 | successor operation and is written more tersely as ~(+1)~. More generally, ~(⊕r) =
215 | λ x → x ⊕ r~.
216 |
217 | The usual arithmeic operations are ~+, /, *, -~ but ~%~ is used to make fractions.
218 |
219 | The Boolean operations are ~==, /=, &&, ||~ for equality, discrepancy,
220 | conjunction, and disjunction.
221 |
222 | * Types
223 |
224 | Type are inferred, but it is better to write them explicitly so that /you
225 | communicate your intentions to the machine/. If you /think/ that expression ~e~ has
226 | type ~τ~ then write ~e :: τ~ to /communicate/ that to the machine, which will silently
227 | accept your claim or reject it loudly.
228 |
229 | | Type | Name | Example Value |
230 | |--------------------+-------------+-----------------------|
231 | | Small integers | ~Int~ | ~42~ |
232 | | Unlimited integers | ~Integer~ | ~7376541234~ |
233 | | Reals | ~Float~ | ~3.14~ and ~2 % 5~ |
234 | | Booleans | ~Boolean~ | ~True~ and ~False~ |
235 | | Characters | ~Char~ | ~'a'~ and ~'3'~ |
236 | | Strings | ~String~ | ~"salam"~ |
237 | | Lists | ~[α]~ | ~[]~ or ~[x₁, …, xₙ]~ |
238 | | Tuples | ~(α, β, γ)~ | ~(x₁, x₂, x₃)~ |
239 | | Functions | ~α → β~ | ~λ x → ⋯~ |
240 |
241 | /Polymorphism/ is the concept that allows one function to operate on different types.
242 | - A function whose type contains /variables/ is called a /polymorphic function/.
243 | - The simplest polymorphic function is ~id ∷ a -> a~, defined by ~id x = x~.
244 |
245 | * Tuples
246 |
247 | *Tuples* ~(α₁, …, αₙ)~ are types with values written ~(x₁, …, xₙ)~ where
248 | each ~xᵢ :: αᵢ~. The are a form of ‘record’ or ‘product’ type.
249 |
250 | E.g., ~(True, 3, 'a') :: (Boolean, Int, Char)~.
251 |
252 | Tuples are used to “return multiple values” from a function.
253 |
254 | Two useful functions on tuples of length 2 are:
255 | #+begin_src haskell
256 | fst :: (α, β) → α
257 | fst (x, y) = x
258 |
259 | snd :: (α, β) → β
260 | snd (x, y) = β
261 | #+end_src
262 |
263 | If in addition you ~import Control.Arrow~ then you may use:
264 | #+begin_src haskell
265 | first :: (α → τ) → (α, β) → (τ, β)
266 | first f (x, y) = (f x, y)
267 |
268 | second :: (β → τ) → (α, β) → (α, τ)
269 | second g (x, y) = (x, g y)
270 |
271 | (***) :: (α → α′) → (β → β) → (α, β) → (α′, β′)
272 | (f *** g) (x, y) = (f x, g y)
273 |
274 | (&&&) :: (τ → α) → (τ → β) → τ → (α, β)
275 | (f &&& g) x = (f x, g x)
276 | #+end_src
277 |
278 | * Lists
279 |
280 | *Lists* are sequences of items of the same type.
281 |
282 | If each ~xᵢ ∷ α~ then ~[x₁, …, xₙ] ∷ [α]~.
283 |
284 | Lists are useful for functions that want to ‘non-deterministicly’ return a
285 | value: They return a list of all possible values.
286 |
287 | - The /empty list/ is ~[]~
288 | - We “cons”truct nonempty lists using ~(:) ∷ α → [α] → [α]~
289 | - Abbreviation: ~[x₁, …, xₙ] = x₁ ∶ (x₂ ∶ (⋯ (xₙ ∶ [])))~
290 | - /List comprehensions/: ~[f x | x <- xs, p x]~ is the list of elements
291 | ~f x~ where ~x~ is an element from list ~xs~ and ~x~ satisfies the property ~p~
292 | - E.g., ~[2 * x | x <- [2, 3, 4], x < 4] ≈ [2 * 2, 2 * 3] ≈ [4, 6]~
293 | - Shorthand notation for segments: ~u~ may be ommitted to yield /infinite lists/
294 | - ~[l .. u] = [l, l + 1, l + 2, …, u]~.
295 | - ~[a, b, .., u] = [a + i * step | i <- [0 .. u - a] ] where step = b - a~
296 |
297 | *Strings* are just lists of characters: ~"c₀c₁…cₙ" ≈ ['c₀', …, 'cₙ']~.
298 | - Hence, all list methods work for strings.
299 |
300 | ** Pattern Matching on Lists
301 | *Pattern matching on lists*
302 | #+begin_src haskell
303 | prod [] = 1
304 | prod (x:xs) = x * prod xs
305 |
306 | fact n = prod [1 .. n]
307 | #+end_src
308 |
309 | If your function needs a case with a list of say, length 3, then you can match
310 | directly on that /shape/ via ~[x, y, z]~ ---which is just an abbreviation for the
311 | shape ~x:y:z:[]~. Likewise, if we want to consider lists of length /at least 3/ then
312 | we match on the shape ~x:y:z:zs~. E.g., define the function that produces the
313 | maximum of a non-empty list, or the function that removes adjacent duplicates
314 | ---both require the use of guards.
315 |
316 | ** Common Methods on Lists
317 | #+begin_src haskell
318 | [x₀, …, xₙ] !! i = xᵢ
319 | [x₀, …, xₙ] ++ [y₀, …, yₘ] = [x₀, …, xₙ, y₀, …, yₘ]
320 | concat [xs₀, …, xsₙ] = xs₀ ++ ⋯ ++ xsₙ
321 |
322 | {- Partial functions -}
323 | head [x₀, …, xₙ] = x₀
324 | tail [x₀, …, xₙ] = [x₁, …, xₙ]
325 | init [x₀, …, xₙ] = [x₀, …, xₙ₋₁]
326 | last [x₀, …, xₙ] = xₙ
327 |
328 | take k [x₀, …, xₙ] = [x₀, …, xₖ₋₁]
329 | drop k [x₀, …, xₙ] = [xₖ, …, xₙ]
330 |
331 | sum [x₀, …, xₙ] = x₀ + ⋯ + xₙ
332 | prod [x₀, …, xₙ] = x₀ * ⋯ * xₙ
333 | reverse [x₀, …, xₙ] = [xₙ, …, x₀]
334 | elem x [x₀, …, xₙ] = x == x₀ || ⋯ || x == xₙ
335 |
336 | zip [x₀, …, xₙ] [y₀, …, yₘ] = [(x₀, y₀), …, (xₖ, yₖ)] where k = n `min` m
337 | unzip [(x₀, y₀), …, (xₖ, yₖ)] = ([x₀, …, xₖ], [y₀, …, yₖ])
338 | #+end_src
339 |
340 | [[https://en.wikipedia.org/wiki/Conjugacy_class][*Duality*]]: Let ~∂f = reverse . f . reverse~, then ~init = ∂ tail~ and
341 | ~take k = ∂ (drop k)~; even ~pure . head = ∂ (pure . last)~ where ~pure x = [x]~.
342 |
343 | * List ‘Design Patterns’
344 |
345 | Many functions have the same ‘form’ or ‘design pattern’, a fact which is
346 | taken advantage of by defining /higher-order functions/ to factor out the
347 | structural similarity of the individual functions.
348 |
349 | ** Map
350 |
351 | ~map f xs = [f x | x <- xs]~
352 | - Transform all elements of a list according to the function ~f~.
353 |
354 | ** Filter
355 | ~filter p xs = [x | x <- xs, p x]~
356 | - Keep only the elements of the list that satisfy the predicate ~p~.
357 | - ~takeWhile p xs~ ≈ Take elements of ~xs~ that satisfy ~p~, but stop stop at
358 | the first element that does not satisfy ~p~.
359 | - ~dropWhile p xs~ ≈ Drop all elements until you see one that does not satisfy
360 | the predicate.
361 | - ~xs = takeWhile p xs ++ dropWhile p xs~.
362 |
363 | ** Fold
364 | Right-folds let us ‘sum’ up the elements of the list, associating to the right.
365 | #+begin_src haskell
366 | foldr (⊕) e ≈ λ (x₀ : (x₁ : (… : (xₙ : []))))
367 | → (x₀ ⊕ (x₁ ⊕ (… ⊕ (xₙ ⊕ e))))
368 | #+end_src
369 |
370 | This function just replaces cons ~“∶”~ and ~[]~ with ~⊕~ and ~e~. That's all.
371 | - E.g., replacing ~:,[]~ with themselves does nothing: ~foldr (:) [] = id~.
372 |
373 | #+latex: \newpage
374 | /All functions on lists can be written as folds!/
375 | #+begin_src haskell
376 | h [] = e ∧ h (x:xs) = x ⊕ h xs
377 | ≡ h = foldr (λ x rec_call → x ⊕ rec_call) e
378 | #+end_src
379 | - Look at the two cases of a function and move them to the two
380 | first arguments of the fold.
381 | - ~map f = foldr (λ x ys → f x : ys) []~
382 | - ~filter p = foldr (λ x ys → if (p x) then (x:ys) else ys) []~
383 | - ~takeWhile p = foldr (λ x ys → if (p x) then (x:ys) else []) []~
384 |
385 | You can also fold leftward, i.e., by associating to the left:
386 | #+begin_src haskell
387 | foldl (⊕) e ≈ λ (x₀ : (x₁ : (… : (xₙ : []))))
388 | → (((e ⊕ x₀) ⊕ x₁) ⊕ … ) ⊕ xₙ
389 | #+end_src
390 | Unless the operation ~⊕~ is associative, the folds are generally different.
391 | - E.g., ~foldl (/) 1 [1..n] ≈ 1 / n!~ where ~n ! = product [1..n]~.
392 | - E.g., ~-55 = foldl (-) 0 [1..10] ≠ foldr (-) 0 [1..10] = -5~.
393 |
394 | If ~h~ swaps arguments ---~h(x ⊕ y) = h y ⊕ h x~--- then ~h~ swaps folds:
395 |
396 | ~h . foldr (⊕) e = foldl (⊝) e′~ where ~e′ = h e~ and ~x ⊝ y = x ⊕ h y~.
397 |
398 | E.g., ~foldl (-) 0 xs = - (foldr (+) 0 xs) = - (sum xs)~
399 | and ~n ! = foldr (*) 1 [1..n] = 1 / foldl (/) 1 [1..n]~.
400 |
401 | | /( Floating points are a leaky abstraction! )/ |
402 |
403 | * Algebraic data types
404 |
405 | When we have ‘possible scenarios’, we can make a type to consider each option.
406 | E.g., ~data Door = Open | Closed~ makes a new datatype with two different values.
407 | Under the hood, ~Door~ could be implemented as integers and ~Open~ is 0 and ~Closed~
408 | is 1; or any other implementation ---/all that matters/ is that we have a new
409 | type, ~Door~, with two different values, ~Open~ and ~Closed~.
410 |
411 | Usually, our scenarios contain a ‘payload’ of additional information; e.g., ~data
412 | Door2 = Open | Ajar Int | Closed~. Here, we have a new way to construct ~Door~
413 | values, such as ~Ajar 10~ and ~Ajar 30~, that we could interpret as denoting how far
414 | the door is open/. Under the hood, ~Door2~ could be implemented as pairs of
415 | integers, with ~Open~ being ~(0,0)~, ~Ajar n~ being ~(1, n)~, and ~Closed~ being ~(2, 0)~
416 | ---i.e., as the pairs “(value position, payload data)”. Unlike functions, a
417 | value construction such as ~Ajar 10~ cannot be simplified any further; just as the
418 | list value ~1:2:3:[]~ cannot be simplified any further. Remember, the
419 | representation under the hood does not matter, what matters is that we have
420 | three possible /construction forms/ of ~Door2~ values.
421 |
422 | Languages, such as C, which do not support such an “algebraic” approach,
423 | force you, the user, to actually choose a particular representation ---even
424 | though, it does not matter, since we only want /a way to speak of/ “different
425 | cases, with additional information”.
426 |
427 | In general, we declare the following to get an “enumerated type with payloads”.
428 | #+begin_src haskell
429 | data D = C₀ τ₁ τ₂ … τₘ | C₁ ⋯ | Cₙ ⋯ deriving Show
430 | #+end_src
431 | There are =n= constructors ~Cᵢ~ that make /different/ values of type ~D~; e.g., ~C₀ x₁ x₂
432 | … xₘ~ is a ~D~-value whenever each ~xᵢ~ is a ~τᵢ~-value. The ~“deriving Show”~ at the end
433 | of the definition is necessary for user-defined types to make sure that values
434 | of these types can be printed in a standard form.
435 |
436 | We may now define functions on ~D~ by pattern matching on the possible ways to
437 | /construct/ values for it; i.e., by considering the cases ~Cᵢ~.
438 |
439 | In-fact, we could have written ~data D α₁ α₂ … αₖ = ⋯~, so that we speak of “D
440 | values /parameterised/ by types αᵢ”. E.g., “lists whose elements are of type α” is
441 | defined by ~data List α = Nil | Cons α (List α)~ and, for example, ~Cons 1 (Cons 2
442 | Nil)~ is a value of ~List Int~, whereas ~Cons 'a' Nil~ is of type ~List Char~. ---The
443 | ~List~ type is missing the ~“deriving Show”~, see below for how to /mixin/ such a
444 | feature.
445 |
446 | For example, suppose we want to distinguish whether we have an α-value or a
447 | β-value, we use ~Either~. Let's then define an example /infix/ function using
448 | pattern matching.
449 | #+begin_src haskell
450 | data Either α β = Left α | Right β
451 |
452 | (+++) :: (α → α′) → (β → β′) → Either α β → Either α′ β′
453 | (f +++ g) (Left x) = Left $ f x
454 | (f +++ g) (Right x) = Right $ g x
455 |
456 | right :: (β → τ) → Either α β → Either α τ
457 | right f = id +++ f
458 | #+end_src
459 | The above ~(+++)~ can be found in ~Control.Arrow~ and is also known as ~either~ in the
460 | standard library.
461 |
462 | * Typeclasses and overloading
463 |
464 | /Overloading/ is using the same name to designate operations “of the same nature”
465 | on values of different types.
466 |
467 | E.g., the ~show~ function converts its argument into a string; however, it is not
468 | polymorphic: We cannot define ~show :: α → String~ with one definition since some
469 | items, like functions or infinite datatypes, cannot be printed and so this is
470 | not a valid type for the function ~show~.
471 |
472 | Haskell solves this by having ~Show~ /typeclass/ whose /instance types/ ~α~ each
473 | implement a definition of the /class method/ ~show~. The type of ~show~ is written
474 | ~Show α => α -> String~: /Given an argument of type ~α~, look in the global listing of
475 | ~Show~ instances, find the one for ~α~, and use that;/ if ~α~ has no ~Show~ instance,
476 | then we have a type error. One says “the type variable ~α~ has is /restricted/ to be
477 | a ~Show~ instance” ---as indicated on the left side of the ~“=>”~ symbol.
478 |
479 | E.g., for the ~List~ datatype we defined, we may declare it to be ‘showable’ like
480 | so:
481 | #+begin_quote
482 | #+begin_src haskell -n 1
483 | instance Show a => Show (List a) where
484 | show Nil = "Nope, nothing here"
485 | show (Cons x xs) = "Saw " ++ show x ++ ", then " ++ show xs
486 | #+end_src
487 | #+end_quote
488 | That is:
489 | 1. /If ~a~ is showable, then ~List a~ is also showable./
490 | 2. /Here's how to show ~Nil~ directly./
491 | 3. /We show ~Cons x xs~ by using the ~show~ of ~a~ on ~x~, then recursively showing ~xs~./
492 |
493 | | | Common Typeclasses |
494 | |---------------+----------------------------------------------------|
495 | | ~Show~ | Show elements as strings, ~show~ |
496 | | ~Read~ | How to read element values from strings, ~read~ |
497 | | ~Eq~ | Compare elements for equality, ~==~ |
498 | | ~Num~ | Use literals ~0, 20, …,~ and arithmetic ~+, *, -~ |
499 | | ~Ord~ | Use comparison relations ~>, <, >=, <=~ |
500 | | ~Enum~ | Types that can be listed, ~[start .. end]~ |
501 | | ~Monoid~ | Types that model ‘(untyped) composition’ |
502 | | ~Functor~ | /Type formers/ that model effectful computation |
503 | | ~Applicative~ | Type formers that can sequence effects |
504 | | ~Monad~ | Type formers that let effects depend on each other |
505 |
506 | The ~Ord~ typeclass is declared ~class Eq a => Ord a where ⋯~, so that all ordered
507 | types are necessarily also types with equality. One says ~Ord~ is a /subclass/ of
508 | ~Eq~; and since subclasses /inherit/ all functions of a class, we may always replace
509 | ~(Eq a, Ord a) => ⋯~ by ~Ord a => ⋯~.
510 |
511 | You can of-course define your own typeclasses; e.g., the ~Monoid~ class in Haskell
512 | could be defined as follows.
513 | #+begin_src haskell
514 | class Semigroup a where
515 | (<>) :: a -> a -> a {- A way to “compose” elements together -}
516 | {- Axiom: (x <> y) <> z = x <> (y <> z) -}
517 |
518 | class Semigroup a => Monoid a where
519 | mempty :: a {- Axiom: This is a ‘no-op’, identity, for composition <> -}
520 | #+end_src
521 | Example monoids ~(α, <>, mempty)~ include ~(Int, +, 0)~, ~([α], ++, [])~, and
522 | (Program statements, sequence “;”, the empty statement) ---this
523 | last example is approximated as ~Term~ with ‘let-in’ clauses at the end of this
524 | cheatsheet. /Typeclasses are interfaces, possibly with axioms specifying their
525 | behaviour./
526 |
527 | As shown earlier, Haskell provides a the ~deriving~ mechanism for making it easier
528 | to define instances of typeclasses, such as ~Show, Read, Eq, Ord, Enum~. How?
529 | Constructor names are printed and read as written as written in the ~data~
530 | declaration, two values are equal if they are formed by the same construction,
531 | one value is less than another if the constructor of the first is declared in
532 | the ~data~ definition before the constructor of the second, and similarly for
533 | listing elements out.
534 | * Functor
535 |
536 | /Functors are type formers that “behave” like collections: We can alter their/
537 | /“elements” without messing with the ‘collection structure’ or ‘element
538 | positions’./ The well-behavedness constraints are called /the functor axioms/.
539 | #+begin_src haskell
540 | class Functor f where
541 | fmap :: (α → β) → f α → f β
542 |
543 | (<$>) = fmap {- An infix alias -}
544 | #+end_src
545 |
546 | The axioms cannot be checked by Haskell, so we can form instances that fail to
547 | meet the implicit specifications ---two examples are below.
548 |
549 | ** Identity Axiom
550 |
551 | *Identity Law*: ~fmap id = id~
552 |
553 | /Doing no alteration to the contents of a collection does nothing to the collection./
554 |
555 | This ensures that “alterations don't needlessly mess with element values”
556 | e.g., the following is not a functor since it does.
557 | #+begin_src haskell :tangle probably.hs
558 | {- I probably have an item -}
559 | data Probably a = Chance a Int
560 |
561 | instance Functor Probably where
562 | fmap f (Chance x n) = Chance (f x) (n `div` 2)
563 | #+end_src
564 |
565 | ** Fusion Axiom
566 | *Fusion Law:* ~fmap f . fmap g = fmap (f . g)~
567 |
568 | /Reaching into a collection and altering twice is the same as reaching in and
569 | altering once./
570 |
571 | This ensures that “alterations don't needlessly mess with collection structure”;
572 | e.g., the following is not a functor since it does.
573 |
574 | #+begin_src haskell :tangle pocket.hs
575 | import Prelude hiding (Left, Right)
576 |
577 | {- I have an item in my left or my right pocket -}
578 | data Pocket a = Left a | Right a
579 |
580 | instance Functor Pocket where
581 | fmap f (Left x) = Right (f x)
582 | fmap f (Right x) = Left (f x)
583 | #+end_src
584 |
585 | ** Functors do not necessarily ‘contain’ anything
586 |
587 | It is important to note that functors model well-behaved container-like types,
588 | but of-course the types do not actually need to contain anything at all! E.g.,
589 | the following is a valid functor.
590 | #+begin_src haskell :tangle Liar.hs
591 | {- “I totally have an α-value, it's either here or there.” Lies! -}
592 | data Liar α = OverHere Int | OverThere Int
593 |
594 | instance Functor Liar where
595 | fmap f (OverHere n) = OverHere n
596 | fmap f (OverThere n) = OverThere n
597 | #+end_src
598 | Notice that if we altered ~n~, say by dividing it by two, then we break the
599 | identity law; and if we swap the constructors, then we break the fusion law.
600 | Super neat stuff!
601 |
602 | In general, functors take something boring and generally furnish it with
603 | ‘coherent’ structure, but *there is not necessarily an α ‘inside’ f α*.
604 | E.g., ~f α = (ε → α)~ has as values “recipes for forming an α-value”,
605 | but unless executed, there is no ~α~-value.
606 |
607 | ** Misc results about Functors
608 |
609 | #+latex: \vspace{0.5em}
610 | - ~fmap f xs~ ≈ /for each/ element ~x~ in the ‘collection’ ~xs~, yield ~f x~.
611 | - Haskell can usually ~derive~ functor instances since they are [[http://archive.fo/U8xIY][unique]]: Only one
612 | possible definition of ~fmap~ will work.
613 | - Reading the functor axioms left-to-right, they can be seen as /optimisation laws/
614 | that make a program faster by reducing work.
615 | - The two laws together say /fmap distributes over composition/:
616 | ~fmap (f₁ . f₂ . ⋯ . fₙ) = fmap f₁ . ⋯ . fmap fₙ~ for ~n ≥ 0~.
617 |
618 | *Naturality Theorems:* If ~p ∷ f a → g a~ for some /functors/ ~f~ and ~g~,
619 | then ~fmap f . p = p . fmap f~ for any /function/ ~f~.
620 |
621 | Hence, any generic property ~p ∷ f α → ε~ is invariant over fmaps:
622 | ~p(fmap f xs) = p xs~. E.g., the length of a list does not change even when an
623 | fmap is applied.
624 |
625 | * Functor Examples
626 |
627 | Let ~f₁, f₂~ be functors and ~ε~ be a given type.
628 |
629 | | Type Former | ~f α~ | ~f <$> x~ |
630 | |-------------------------------------------------------------------------------------------------------------+------------------------+---------------------------------------|
631 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Identity.html#t:Identity][Identity]] | ~α~ | ~f <$> x = f x~ |
632 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Applicative.html#t:Const][Constant]] | ~ε~ | ~f <$> x = x~ |
633 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-List.html][List]] | ~[α]~ | ~f <$> [x₀, …, xₙ] = [f x₀, …, f xₙ]~ |
634 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Either.html#t:Either][Either]] | ~Either ε α~ | ~f <$> x = right f~ |
635 | |-------------------------------------------------------------------------------------------------------------+------------------------+---------------------------------------|
636 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Product.html#t:Product][Product]] | ~(f₁ α, f₂ α)~ | ~f <$> (x, y) = (f <$> x, f <$> y)~ |
637 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Compose.html#t:Compose][Composition]] | ~f₁ (f₂ α)~ | ~f <$> x = (fmap f) <$> x~ |
638 | | [[http://comonad.com/reader/2012/abstracting-with-applicatives/][Sum]] | ~Either (f₁ α) (f₂ α)~ | ~f <$> ea = f +++ f~ |
639 | |-------------------------------------------------------------------------------------------------------------+------------------------+---------------------------------------|
640 | | [[http://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Writer-Lazy.html#g:2][Writer]] | ~(ε, α)~ | ~f <$> (e, x) = (e, f x)~ |
641 | | [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Reader.html][Reader]] | ~ε → α~ | ~f <$> g = f . g~ |
642 | | [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-State-Lazy.html#g:2][State]] | ~ε → (ε, α)~ | ~f <$> g = second f . g~ |
643 |
644 | Notice that writer is the product of the constant and the identity functors.
645 |
646 | Unlike reader, the type former ~f α = α → ε~ is /not/ a functor since there is no
647 | way to implement ~fmap~. In contrast, ~f α = (α → ε, α)~ /does/ have an implementation
648 | of ~fmap~, but it is not lawful.
649 |
650 | * Applicative
651 | /Applicatives are collection-like types that can apply collections of functions
652 | to collections of elements./
653 |
654 | In particular, /applicatives can fmap over multiple arguments/; e.g., if we try to
655 | add ~Just 2~ and ~Just 3~, we find =(+) <$> Just 2 :: Maybe (Int → Int)= and this is
656 | not a function and so cannot be applied further to ~Just 3~ to get ~Just 5~.
657 | We have both the function and the value wrapped up, so we need a way to apply
658 | the former to the latter. The answer is ~(+) <$> Just 2 <*> Just 3~.
659 |
660 | #+begin_src haskell
661 | class Functor f => Applicative f where
662 | pure :: a -> f a
663 | (<*>) :: f (a -> b) -> f a -> f b {- “apply” -}
664 |
665 | {- Apply associates to the left: p <*> q <*> r = (p <*> q) <*> r) -}
666 | #+end_src
667 |
668 | The method ~pure~ lets us inject values, to make ‘singleton collections’.
669 |
670 | - /Functors transform values inside collections; applicatives can additionally
671 | combine values inside collections./
672 | - Exercise: If ~α~ is a monoid, then so too is ~f α~ for any applicative ~f~.
673 |
674 | ** Axioms
675 | The applicative axioms ensure that apply behaves like usual functional application:
676 |
677 | - Identity: ~pure id <*> x = x~ ---c.f., ~id x = x~
678 | - Homomorphism: ~pure f <*> pure x = pure (f x)~ ---it really is function application
679 | on pure values!
680 | - Applying a non-effectful function to a non-effectful argument in an effectful
681 | context is the same as just applying the function to the argument and then
682 | injecting the result into the content.
683 | - Interchange: ~p <*> pure x = pure ($ x) <*> p~ ---c.f., ~f x = ($ x) f~
684 | - Functions ~f~ take ~x~ as input ≈ Values ~x~ project functions ~f~ to particular values
685 | - When there is only one effectful component, then it does not matter whether
686 | we evaluate the function first or the argument first, there will still only be
687 | one effect.
688 | - Indeed, this is equivalent to the law: ~pure f <*> q = pure (flip ($)) <*> q <*> pure f~.
689 |
690 | - Composition: ~pure (.) <*> p <*> q <*> r = p <*> (q <*> r)~
691 | ---c.f., ~(f . g) . h = f . (g . h)~.
692 |
693 | If we view ~f α~ as an “effectful computation on α”, then the above laws ensure
694 | ~pure~ creates an “effect free” context. E.g., if ~f α = [α]~ is considered
695 | “nondeterminstic α-values”, then ~pure~ just treats usual α-values as
696 | nondeterminstic but with no ambiguity, and ~fs <*> xs~ reads “if we
697 | nondeterminsticly have a choice ~f~ from ~fs~, and we nondeterminsticly an ~x~ from
698 | ~xs~, then we nondeterminsticly obtain ~f x~.” More concretely, if I'm given
699 | randomly addition or multiplication along with the argument 3 and another
700 | argument that could be 2, 4, or 6, then the result would be obtained by
701 | considering all possible combinations: ~[(+), (*)] <*> pure 3 <*> [2, 4, 6] =
702 | [5,7,9,6,12,18]~. The name ~“<*>”~ is suggestive of this ‘cartesian product’ nature.
703 |
704 | Given a definition of apply, the definition of ~pure~ may be obtained
705 | by unfolding the identity axiom.
706 |
707 | Using these laws, we regain the original ~fmap~ ---since ~fmap~'s are [[http://archive.fo/U8xIY][unique]] in
708 | Haskell--- thereby further cementing that applicatives model “collections that
709 | can be functionally applied”: ~f <$> x = pure f <*> x~. ( Hence, every applicative
710 | is a functor whether we like it or not. )
711 | - The identity applicative law is then just the identity law of functor: ~id <$> x = x~.
712 | - The homomorphism law now becomes: ~pure . f = fmap f . pure~.
713 |
714 | - This is the “naturality law” for ~pure~.
715 |
716 | ** Canonical Form -- =liftN=
717 |
718 | [[http://www.staff.city.ac.uk/~ross/papers/Applicative.pdf][The laws]] may be interpreted as left-to-right rewrite rules and so are a
719 | procedure for transforming any applicative expression into the canonical form
720 | of “a pure function applied to effectful arguments”: ~pure f <*> x₁ <*> ⋯ <*>
721 | xₙ~. In this way, one can compute in-parallel the, necessarily independent, ~xᵢ~
722 | then combine them together.
723 |
724 | Notice that the canonical form generalises ~fmap~ to ~n~-arguments:
725 | Given ~f ∷ α₁ → ⋯ → αₙ → β~ and ~xᵢ ∷ f αᵢ~, we obtain an ~(f β)~-value.
726 | The case of ~n = 2~ is called ~liftA2~, ~n = 1~ is just ~fmap~, and for ~n = 0~ we have
727 | ~pure~!
728 | ** Monoidal Presentation
729 |
730 | Notice that ~lift2A~ is essentially the cartesian product in the setting of lists,
731 | or ~(<&>)~ below ---c.f., ~sequenceA :: Applicative f ⇒ [f a] → f [a]~.
732 |
733 | #+begin_src haskell
734 | (<&>) :: f a → f b → f (a, b) {- Not a standard name! -}
735 | (<&>) = liftA2 (,) -- i.e., p <&> q = (,) <$> p <*> q
736 | #+end_src
737 | This is a pairing operation with properties of ~(,)~ mirrored at the applicative level:
738 | #+begin_src haskell
739 | {- Pure Pairing -} pure x <&> pure y = pure (x, y)
740 | {- Naturality -} (f &&& g) <$> (u <&> v) = (f <$> u) <&> (g <&> v)
741 |
742 | {- Left Projection -} fst <$> (u <&> pure ()) = u
743 | {- Right Projection -} snd <$> (pure () <&> v) = v
744 | {- Associtivity -} assocl <$> (u <&> (v <&> w)) = (u <&> v) <&> w
745 | #+end_src
746 | The final three laws above suffice to prove the original applicative axioms, and so
747 | we may define ~p <*> q = uncurry ($) <$> (p <&> q)~.
748 |
749 | * Applicative Examples
750 |
751 | Let ~f₁, f₂~ be functors and let ~ε~ a type.
752 |
753 | | Functor | ~f α~ | ~f <*> x~ |
754 | |-------------------------------------------------------------------------------------------------------------+------------------------+---------------------------------------------|
755 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Identity.html#t:Identity][Identity]] | ~α~ | ~f <*> x = f x~ |
756 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Applicative.html#t:Const][Constant]] | ~ε~ | ~e <*> d = e <> d~ |
757 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-List.html][List]] | ~[α]~ | =fs <*> xs = [f x ∣ f <- fs, x <- xs]= |
758 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Either.html#t:Either][Either]] | ~Either ε α~ | ~ef <*> ea = right (λ f → right f ea) ef~ |
759 | |-------------------------------------------------------------------------------------------------------------+------------------------+---------------------------------------------|
760 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Compose.html#t:Compose][Composition]] | ~f₁ (f₂ α)~ | ~f <*> x = (<*>) <$> f <*> x~ |
761 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Product.html#t:Product][Product]] | ~(f₁ α, f₂ α)~ | ~(f, g) <*> (x, y) = (f <*> x, g <*> y)~ |
762 | | [[http://comonad.com/reader/2012/abstracting-with-applicatives/][Sum]] | ~Either (f₁ α) (f₂ α)~ | Challenge: Assume ~η ∷ f₁ a → f₂ a~ |
763 | |-------------------------------------------------------------------------------------------------------------+------------------------+---------------------------------------------|
764 | | [[http://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Writer-Lazy.html#g:2][Writer]] | ~(ε, α)~ | ~(a , f) <*> (b, x) = (a <> b, f x)~ |
765 | | [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Reader.html][Reader]] | ~ε → α~ | ~f <*> g = λ e → f e (g e)~ ---c.f., ~SKI~ |
766 | | [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-State-Lazy.html#g:2][State]] | ~ε → (ε, α)~ | ~sf <*> sa = λ e → let (e′, f) = sf e~ |
767 | | | | ~in second f (sa e′)~ |
768 |
769 | In the writer and constant cases, we need ~ε~ to also be a monoid.
770 | When ε is /not/ a monoid, then those two constructions give examples of functors
771 | that are /not/ applicatives ---since there is no way to define ~pure~.
772 | In contrast, ~f α = (α → ε) → Maybe ε~ is not an applicative since no
773 | definition of apply is lawful.
774 |
775 | Since readers ~((->) r)~ are applicatives, we may, for example, write ~(⊕) <$> f
776 | <*> g~ as a terse alternative to the “pointwise ⊕” method ~λ x → f x ⊕ g x~. E.g.,
777 | using ~(&&)~ gives a simple way to chain predicates.
778 |
779 | * ~Do~-Notation ---Subtle difference between applicatives and monads
780 | Recall the ~map~ operation on lists, we could define it ourselves:
781 | #+begin_src haskell :tangle delme.hs
782 | map' :: (α -> β) -> [α] -> [β]
783 | map' f [] = []
784 | map' f (x:xs) = let y = f x
785 | ys = map' f xs
786 | in (y:ys)
787 | #+end_src
788 | If instead the altering function ~f~ returned effectful results,
789 | then we could gather the results along with the effect:
790 | #+begin_src haskell :tangle delme1.hs
791 | {-# LANGUAGE ApplicativeDo #-}
792 |
793 | mapA :: Applicative f => (a -> f b) -> [a] -> f [b]
794 | mapA f [] = pure []
795 | mapA f (x:xs) = do y <- f x
796 | ys <- mapA f xs
797 | pure (y:ys)
798 | {- ≈ (:) <$> f x <*> mapA f xs -}
799 | #+end_src
800 |
801 | Applicative syntax can be a bit hard to write, whereas ~do~-notation is more
802 | natural and reminiscent of the imperative style used in defining ~map'~ above. For
803 | instance, the intuition that ~fs <*> ps~ is a cartesian product is clearer in
804 | do-notation: ~fs <*> ps ≈ do {f ← fs; x ← ps; pure (f x)}~ where the right side is
805 | read /“for-each f in fs, and each x in ps, compute f x”/.
806 |
807 | #+latex: \columnbreak
808 |
809 | [[https://dl.acm.org/doi/pdf/10.1145/3241625.2976007][In-general]], ~do {x₁ ← p₁; …; xₙ ← pₙ; pure e} ≈ pure (λ x₁ … xₙ → e) <*> p₁ <*> ⋯
810 | <*> pₙ~ *provided* ~pᵢ~ does not mention ~xⱼ~ for ~j < i~; but =e= may refer to all ~xᵢ~. If
811 | any ~pᵢ~ mentions an earlier ~xⱼ~, then we could not translate the ~do~-notation into
812 | an applicative expression.
813 |
814 | If ~do {x ← p; y ← qx; pure e}~ has ~qx~ being an expression *depending* on ~x~,
815 | then we could say this is an abbreviation for ~(λ x → (λ y → e) <$> qx) <$> p~
816 | but this is of type ~f (f β))~. Hence, to allow later computations to depend
817 | on earlier computations, we need a method ~join :: f (f α) → f α~ with which
818 | we define ~do {x ← p; y ← qx; pure e} ≈ join $ ~(λ x -> (λ y → e) <$> qx) <$> p~.
819 |
820 | Applicatives with a ~join~ are called monads and they give us a *“programmable
821 | semicolon”*. Since later items may depend on earlier ones, ~do {x ← p; y ← q;
822 | pure e}~ could be read /“let x be the value of computation p, let y be the value
823 | of computation q, then combine the values via expression e”/. Depending on how
824 | ~<*>~ is implemented, such ‘let declarations’ could short-circuit (~Maybe~) or be
825 | nondeterministic (~List~) or have other effects such as altering state.
826 |
827 | As the ~do~-notation clearly shows, the primary difference between =Monad= and
828 | =Applicative= is that =Monad= allows dependencies on previous results, whereas
829 | =Applicative= does not.
830 |
831 | ** Do-notation with tuples and functions
832 |
833 | Do-syntax also works with tuples and functions --c.f., reader monad below---
834 | since they are monadic; e.g., every clause ~x <- f~ in a functional do-expression
835 | denotes the resulting of applying ~f~ to the (implicit) input.
836 | More concretely:
837 | #+begin_src haskell
838 | go :: (Show a, Num a) => a -> (a, String)
839 | go = do {x <- (1+); y <- show; return (x, y)}
840 |
841 | -- go 3 = (4, "3")
842 | #+end_src
843 |
844 | Likewise, tuples, lists, etc.
845 |
846 | * Formal Definition of ~Do~-Notation
847 |
848 | For a general applicative ~f~, a ~do~ expression has the form ~do {C; r}~, where ~C~ is
849 | a (possibly empty) list of commands separated by semicolons, and ~r~ is an
850 | expression of type ~f β~, which is also the type of the entire ~do~ expression. Each
851 | command takes the form ~x ← p~, where ~x~ is a variable, or possibly a pattern; if ~p
852 | :: f α~ then ~x :: α~. In the particular case of the anonymous variable, ~_ ← p~ may
853 | be abbreviated to ~p~.
854 |
855 | The translation of a ~do~ expression into ~<*>/join~ operations and ~where~ clauses is
856 | governed by three rules ---the last one only applies in the setting of a monad.
857 | #+begin_src haskell
858 | (1) do {r} = r
859 | (2A) do {x ← p; C; r} = q <*> p where q x = do {C; r} --Provided x ∉ C
860 | (2M) do {x ← p; C; r} = join $ map q p where q x = do {C; r}
861 |
862 | {- Fact: When x ∉ C, (2A) = (2M). -}
863 | #+end_src
864 |
865 | By definition chasing and induction on the number of commands ~C~, we have:
866 | #+begin_src haskell
867 | [CollapseLaw] do {C; do {D; r}} = do {C; D; r}
868 | #+end_src
869 | Likewise:
870 | #+begin_src haskell
871 | [Map ] fmap f p = do {x ← p; pure (f x)} -- By applicative laws
872 | [Join] join ps = do {p ← ps; p} -- By functor laws
873 | #+end_src
874 |
875 | *Do-Notation Laws*: Here are some desirable usability properties of ~do~-notation.
876 | #+begin_src haskell
877 | [RightIdentity] do {B; x ← p; pure x} = do {B; p}
878 | [LeftIdentity ] do {B; x ← pure e; C; r} = do {B; C[x ≔ e]; r[x ≔ e]}
879 | [Associtivity ] do {B; x ← do {C; p}; D; r} = do {B; C; x ← p; D; r}
880 | #+end_src
881 |
882 | Here, ~B, C, D~ range over sequences of commands and ~C[x ≔ e]~ means the sequence ~C~
883 | with all free occruences of ~x~ replaced by ~e~.
884 |
885 | - Associtivity gives us a nice way to ‘inline’ other calls.
886 | - The LeftIdentity law, read right-to-left, lets us “locally give a name” to the
887 | possibly complex expression ~e~.
888 |
889 | If ~pure~ forms a singleton collection, then LeftIdentity is a “one-point rule”:
890 | We consider /all/ ~x ← pure e~, but there is only /one/ such ~x~, namely ~e~!
891 |
892 | In the applicative case, where the clauses are independent, we can prove, say,
893 | ~RightIdentity~ using the identity law for applicatives ---which says essentially
894 |
895 | ~do {x <- p; pure x} = p~--- then apply induction on the length of ~B~.
896 |
897 | What axioms are needed for the monad case to prove the ~do~-notation laws?
898 |
899 | * Monad Laws
900 | Here is the definition of the monad typeclass.
901 | #+begin_src haskell :tangle del_4.hs
902 | class Applicative m => Monad (m :: * -> *) where
903 | (>>=) :: m a -> (a -> m b) -> m b
904 |
905 | (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
906 | f <=< g = join . fmap f . g
907 | #+end_src
908 |
909 | Where's ~join~!? Historically, monads entered Haskell first with interface ~(>>=),
910 | return~; later it was realised that ~return = pure~ and the relationship with
911 | applicative was cemented.
912 |
913 | ‘Bind’ ~(>>=)~ is definable from ~join~ by ~ma >>= f = join (fmap f ma)~, and, for
914 | this reason, bind is known as “flat map” or “concat map” in particular
915 | instances. For instance, the second definition of ~do~-notation could be
916 | expressed:
917 | #+begin_src haskell
918 | (2M′) do {x ← p; C; r} = p >>= q where q x = do {C; r}
919 | #+end_src
920 | Conversely, ~join ps = do {p ← ps; p} = ps >>= id~. Likewise, with (2M′), note how
921 | ~(<*>)~ can be defined directly in-terms of ~(>>=)~
922 |
923 | ---c.f., ~mf <*> mx = do {f ← mf;
924 | x ← mx; return (f x)}~.
925 |
926 | Since ~fmap f p = do {x ← p; return (f x)} = p >>= return . f~, in the past monad
927 | did not even have functor as a superclass ---c.f., [[http://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Monad.html#v:liftM][liftM]].
928 |
929 | The properties of ~>>=, return~ that prove the desired ~do~-notation laws are:
930 | #+begin_src haskell
931 | [LeftIdentity ] return a >>= f ≡ f a
932 | [RightIdentity] m >>= return ≡ m
933 | [Associtivity ] (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
934 | i.e., (m >>= (\x -> f x)) >>= g
935 | = m >>= (\x -> f x >>= g)
936 | #+end_src
937 |
938 | Equivalently, show the ‘fish’ ~(<=<)~ is associative with identity being ~pure~
939 | ---c.f., monoids!
940 |
941 | It is pretty awesome that ~(>>=), return~ give us a functor, an applicative, and
942 | (dependent) do-notation! Why? Because bind does both the work of ~fmap~ and ~join~.
943 | Thus, ~pure, fmap, join~ suffice to characterise a monad.
944 |
945 | | /Join determines how a monad behaves!/ |
946 |
947 | The monad laws can be expressed in terms of ~join~ [[https://en.wikibooks.org/wiki/Haskell/Category_theory#The_monad_laws_and_their_importance][directly]]:
948 | #+begin_src haskell
949 | [Associativity] join . fmap join = join . join
950 | {- The only two ways to get from “m (m (m α))” to “m α” are the same. -}
951 |
952 | [Identity Laws] join. fmap pure = join . pure = id
953 | {- Wrapping up “m α” gives an “m (m α)” which flattens to the original element. -}
954 | #+end_src
955 |
956 | Then, notice that the (free) naturality of join is:
957 | #+begin_src haskell
958 | join . fmap (fmap f) = fmap f . join ∷ m (m α) → m β
959 | #+end_src
960 |
961 | Again, note that ~join~ doesn't merely flatten a monad value, but rather performs
962 | the necessary logic that determines /how the monad behaves/.
963 |
964 | E.g., suppose ~m α = ε → (ε, α)~ is the type of ~α~-values that can be configured
965 | according to a fixed environment type ~ε~, along with the possibly updated
966 | configuration ---i.e., functions ~ε → (ε, α)~. Then any ~a ∶ ε → (ε, ε → (ε, α))~ in ~m
967 | (m α)~ can be considered an element of ~m α~ if we /propagate the environment
968 | configuration/ through the outer layer to obtain a new configuration for the
969 | inner layer: ~λ e → let (e′, a′) = a e in a′ e′~. The join dictates how a
970 | configuration is /modified then passed along/: We have two actions, ~a~ and ~a′~, and
971 | join has /sequenced/ them by pushing the environment through the first thereby
972 | modifying it then pushing it through the second.
973 |
974 | * Monad Examples
975 |
976 | Let ~f₁, f₂~ be functors and let ~ε~ a type.
977 |
978 | | Applicative | ~m α~ | ~join :: m (m α) → m α~ |
979 | |-------------------------------------------------------------------------------------------------------------+----------------+---------------------------------------------------------------------|
980 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Identity.html#t:Identity][Identity]] | ~α~ | ~λ x → x~ |
981 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Applicative.html#t:Const][Constant]] | ~ε~ | ~λ x → x~ ---Shucks! |
982 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-List.html][List]] | ~[α]~ | ~λ xss → foldr (++) [] xss~ |
983 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Either.html#t:Either][Either]] | ~Either ε α~ | Exercise ^_^ |
984 | |-------------------------------------------------------------------------------------------------------------+----------------+---------------------------------------------------------------------|
985 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Compose.html#t:Compose][Composition]] | ~f₁ (f₂ α)~ | [[https://stackoverflow.com/q/7040844/3550444][Nope! Not a monad!]] |
986 | | [[https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor-Product.html#t:Product][Product]] | ~(f₁ α, f₂ α)~ | ~λ p → (fst <$> p, snd <$> p)~ |
987 | |-------------------------------------------------------------------------------------------------------------+----------------+---------------------------------------------------------------------|
988 | | [[http://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Writer-Lazy.html#g:2][Writer]] | ~(ε, α)~ | ~λ (e, (e′, a)) → (e <> e′, a)~ |
989 | | [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Reader.html][Reader]] | ~ε → α~ | ~λ ra → λ e → ra e e~ |
990 | | [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-State-Lazy.html#g:2][State]] | ~ε → (ε, α)~ | ~λ ra → λ e → let (e′, a) = ra e in a e′~ |
991 |
992 | In writer, we need ~ε~ to be a monoid.
993 |
994 | - Notice how, in writer, join merges the outer context with the inner context:
995 | /Sequential writes are mappended together!/
996 | - If ~pure~ forms ‘singleton containers’ then ~join~ flattens containers of containers
997 | into a single container.
998 |
999 | Excluding the trivial monoid, the constant functor is /not/ a monad: It fails the
1000 | monad identity laws for join. Similarly, ~f α = Maybe (α, α)~ is an applicative
1001 | but /not/ a monad ---since there is no lawful definition of ~join~. Hence,
1002 | applicatives are strictly more generally than monads.
1003 |
1004 | * Running Example ---A Simple Arithmetic Language
1005 |
1006 | Let's start with a weak language:
1007 | #+begin_src haskell :tangle simple_terms.hs
1008 | data Term = Int Int | Div Term Term deriving Show
1009 |
1010 | thirteen = Int 1729 `Div` (Int 133 `Div` Int 1)
1011 | boom = Int 1729 `Div` (Int 12 `Div` Int 0)
1012 |
1013 | eval₀ :: Term -> Int
1014 | eval₀ (Int n) = n
1015 | eval₀ (n `Div` d) = let top = eval₀ n
1016 | bottom = eval₀ d
1017 | in top `div` bottom
1018 | #+end_src
1019 |
1020 | How do we accomodate safe division by zero? Print to the user what's happening
1021 | at each step of the calcuation? Have terms that access ‘global’ variables? Have
1022 | terms that can store named expressions then access them later?
1023 |
1024 | We'll make such languages and their ~eval~'s will be nearly just as simple as this
1025 | one (!) but accomodate these other issues.
1026 |
1027 | * [[http://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Maybe.html][Maybe]] ---Possibly Failing Computations
1028 | Safe evaluator: No division errors.
1029 | #+begin_src haskell :tangle simple_terms.hs
1030 | eval₁ :: Term -> Maybe Int
1031 | eval₁ (Int n) = pure n
1032 | eval₁ (n `Div` d) = do t <- eval₁ n
1033 | b <- eval₁ d
1034 | if b == 0 then Nothing else pure (t `div` b)
1035 | #+end_src
1036 | Exercise: Rewrite ~evalᵢ~ without ~do~-notation and you'll end-up with nested case
1037 | analysis leading into a straicase of code that runs right off the page.
1038 |
1039 | - Applicative is enough for ~eval₁, eval₂, eval₃~, but ~eval₄~ needs ~Monad~.
1040 |
1041 | * [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Writer-Lazy.html#g:2][Writer]] ---Logging Information as we Compute
1042 |
1043 | Use a pair type ~W ε α~ to keep track of an environment ~ε~ and a value ~α~.
1044 | #+begin_src haskell :tangle simple_terms.hs
1045 | data Writer ε α = W ε α deriving Show
1046 |
1047 | write :: ε -> Writer ε ()
1048 | write e = W e ()
1049 |
1050 | instance Functor (Writer ε) where
1051 | fmap f (W e a) = W e (f a)
1052 | #+end_src
1053 | Aggregate, merge, environments using their monoidal operation.
1054 | #+begin_src haskell :tangle simple_terms.hs
1055 | instance Monoid ε => Applicative (Writer ε) where
1056 | pure a = W mempty a
1057 | (W e f) <*> (W d a) = W (e <> d) (f a)
1058 |
1059 | instance Monoid ε => Monad (Writer ε) where
1060 | (>>=) = \ ma f -> join (pure f <*> ma)
1061 | where join (W e (W d a)) = W (e <> d) a
1062 | #+end_src
1063 |
1064 | An evaluator that prints to the user what's going on.
1065 | #+begin_src haskell :tangle simple_terms.hs
1066 | eval₂ :: Term -> Writer String Int
1067 | eval₂ it@(Int n) = W ("\n Evaluating: " ++ show it) n
1068 | eval₂ it@(n `Div` d) = do write $ "\n Evaluating: " ++ show it
1069 | t <- eval₂ n
1070 | b <- eval₂ d
1071 | pure $ (t `div` b)
1072 |
1073 | -- Try this! With “boom”, we get to see up to the boint of the error ^_^
1074 | -- let W e x = eval₂ thirteen in putStrLn e
1075 | #+end_src
1076 |
1077 | #+latex: \vspace{-1em}
1078 | * [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Reader.html#g:2][Reader]] ---Accessing ‘Global, read-only, data’
1079 | #+latex: \hspace{-1.5em}
1080 | Use a function type ~ε → α~ to get ~α~-values that ‘reads’ from a configuration
1081 | environment ε.
1082 | #+begin_src haskell :tangle terms_with_vars.hs
1083 | data Reader ε α = R {run :: ε -> α}
1084 |
1085 | instance Functor (Reader ε) where
1086 | fmap f (R g) = R $ f . g
1087 |
1088 | instance Applicative (Reader ε) where
1089 | pure a = R $ const a
1090 | (R f) <*> (R g) = R $ \e -> f e (g e) {- “S” combinator -}
1091 |
1092 | instance Monad (Reader ε) where
1093 | ma >>= f = join (pure f <*> ma)
1094 | where join (R rf) = R $ \e -> run (rf e) e
1095 | #+end_src
1096 |
1097 | A language with access to global variables; uninitialised variables are 0 by
1098 | default.
1099 | #+begin_src haskell :tangle terms_with_vars.hs
1100 | data Term = Int Int | Div Term Term | Var String deriving Show
1101 |
1102 | type GlobalVars = [(String, Int)]
1103 |
1104 | valuefrom :: String -> GlobalVars -> Int
1105 | valuefrom x gvs = maybe 0 id $ lookup x gvs
1106 |
1107 | eval₃ :: Term -> Reader GlobalVars Int
1108 | eval₃ (Int x) = pure x
1109 | eval₃ (Var x) = R $ \e -> x `valuefrom` e
1110 | eval₃ (n `Div` d) = do t <- eval₃ n
1111 | b <- eval₃ d
1112 | pure (t `div` b)
1113 |
1114 | state = [("x", 1729), ("y", 133)] :: GlobalVars
1115 | thirteen = Var "x" `Div` (Var "y" `Div` Int 1)
1116 | -- run (eval₃ thirteen) state
1117 | #+end_src
1118 |
1119 | * [[https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-State-Lazy.html#g:2][State]] ---Read and write to local storage
1120 |
1121 | Let's combine writer and reader to get state: We can both read and write to data
1122 | by using functions ~ε → (ε, α)~ that read from an environment ε and result in a
1123 | new environment as well as a value.
1124 | - ~IO α ≅ State TheRealWorld α~ ;-)
1125 | #+begin_src haskell :tangle terms_with_storage.hs
1126 | data State ε α = S {run :: ε -> (ε, α)}
1127 |
1128 | push :: Monoid ε => ε -> State ε ()
1129 | push d = S $ \e -> (d <> e, ())
1130 |
1131 | instance Functor (State ε) where
1132 | fmap f (S g) = S $ \ e -> let (e', a) = g e in (e', f a)
1133 |
1134 | instance Applicative (State ε) where
1135 | pure a = S $ \e -> (e, a)
1136 | (S sf) <*> (S g) = S $ \e -> let (e', a) = g e
1137 | (e'', f) = sf e' in (e'', f a)
1138 |
1139 | instance Monad (State ε) where
1140 | ma >>= f = join (pure f <*> ma)
1141 | where join (S sf) = S $ \e -> let (e', S f) = sf e in f e'
1142 | #+end_src
1143 |
1144 | A simple language with storage; a program's value is the value of its final store.
1145 | #+begin_src haskell :tangle terms_with_storage.hs
1146 | data Expr = Let String Expr Expr | Var String | Int Int | Div Expr Expr
1147 | deriving Show
1148 |
1149 | eval₄ :: Expr -> State GlobalVars Int
1150 | eval₄ (Var x) = S $ \e -> let r = x `valuefrom` e in ((x,r):e, r)
1151 | eval₄ (Int x) = pure x
1152 | eval₄ (Let x t body) = do n <- eval₄ t
1153 | push [(x, n)] -- Applicative is NOT enough here!
1154 | eval₄ body
1155 | eval₄ (n `Div` d) = do t <- eval₄ n; b <- eval₄ d; pure (t `div` b)
1156 |
1157 | thirteen = Let "x" (Int 1729)
1158 | $ Let "y" (Int 133 `Div` Int 1)
1159 | $ Var "x" `Div` Var "y"
1160 |
1161 | -- run (eval₄ thirteen) []
1162 | #+end_src
1163 |
1164 | Exercise: Add to the oringal =Term= type a constructor =Rndm [Term]=, where =Rndm
1165 | [t₁, …, tₙ]= denotes non-deterministicly choosing one of the terms ~tᵢ~. Then write
1166 | an evaluator that considers all possible branches of a computation:
1167 | ~eval₅ : Term → [Int]~.
1168 |
1169 | If we want to mixin any of the features for our evaluators, we need to use ‘monad
1170 | transformers’ since monads do not compose in general.
1171 |
1172 | #+latex: \columnbreak
1173 | * Reads
1174 |
1175 | - /Introduction to Functional Programming/ by Richard Bird
1176 | - Assuming no programming, this book end by showing how to write a theorem
1177 | prover powerful enough to prove many of laws scattered throughout the book.
1178 |
1179 | - [[http://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf][Monads for functional programming]] by Philip Wadler
1180 | - This covers the ~evalᵢ~ and more ^_^
1181 |
1182 | - [[https://docs.racket-lang.org/heresy/monad-do.html][Comprehending Monads]] by Philip Wadler
1183 |
1184 | - [[http://dev.stephendiehl.com/hask/][What I Wish I Knew When Learning Haskell]]
1185 |
1186 | - [[https://wiki.haskell.org/Typeclassopedia][Typeclassopedia]] ---/The essentials of each type class are introduced, with
1187 | examples, commentary, and extensive references for further reading./
1188 |
1189 | - [[http://blog.sigfpe.com/2006/08/you-could-have-invented-monads-and.html][You Could Have Invented Monads! (And Maybe You Already Have.)]]
1190 |
1191 | - [[http://learnyouahaskell.com/chapters][Learn You a Haskell for Great Good]] ---An accessible read with many examples, and drawings
1192 |
1193 | - [[https://en.wikibooks.org/wiki/Haskell][The Haskell WikiBook]] ---Has four beginner's tracks and four advanced tracks
1194 |
1195 | - [[https://alhassy.github.io/CatsCheatSheet/CheatSheet.pdf][Category Theory Cheat Sheet]] ---The “theory of typed composition”:
1196 | Products, Sums, Functors, Natural Transformations ^_^
1197 |
1198 | - [[https://alhassy.github.io/AgdaCheatSheet/CheatSheet.pdf][Agda Cheat Sheet]] ---Agda is Haskell on steroids in that it you can invoke
1199 | Haskell code and write proofs for it.
1200 |
1201 | - LINQ for [[http://tomasp.net/blog/idioms-in-linq.aspx/#csidiomsl][applicatives]] and [[https://livebook.manning.com/book/real-world-functional-programming/chapter-12/28][monads]].
1202 | - Monads ≈ SQL/Linq ≈ Comprehensions/Generators
1203 |
1204 | #+latex: \ifnum\cheatsheetcols=1 \newpage \else \columnbreak \fi
1205 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-merlot
--------------------------------------------------------------------------------