├── .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:

HaskellCheatSheet

1550 | ,#+OPTIONS: toc:nil d:nil 1551 | # Toc is displayed below at a strategic position. 1552 | 1553 | {{{blurb}}} 1554 | 1555 | :Hide: 1556 | This project is to contain a listing of common results in X Theory. 1557 | 1558 | ,*The repo contains other articles I've written on X Theory;* 1559 | ,*which may be read in a blog-format at:* 1560 | https://alhassy.github.io/blog/categories/#Xtheory 1561 | :End: 1562 | 1563 | #+begin_quote 1564 | ,*The listing sheet, as PDF, can be found 1565 | [[https://alhassy.github.io/HaskellCheatSheet/CheatSheet.pdf][here]]*, 1566 | or as a [[https://alhassy.github.io/HaskellCheatSheet/CheatSheet_Portrait.pdf][single column portrait]], 1567 | while below is an unruly html rendition. 1568 | #+end_quote 1569 | 1570 | # Markdown links: [title](target) 1571 | 1572 | This reference sheet is built from a 1573 | [[https://github.com/alhassy/CheatSheet][CheatSheets with Org-mode]] 1574 | system. 1575 | 1576 | #+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 --------------------------------------------------------------------------------