{"id":13496395,"url":"https://github.com/enricopolanski/functional-programming","last_synced_at":"2025-04-08T06:29:52.101Z","repository":{"id":38837989,"uuid":"233225883","full_name":"enricopolanski/functional-programming","owner":"enricopolanski","description":"Introduction to Functional Programming using TypeScript and fp-ts.","archived":false,"fork":false,"pushed_at":"2025-03-11T22:12:55.000Z","size":10466,"stargazers_count":1260,"open_issues_count":10,"forks_count":89,"subscribers_count":19,"default_branch":"master","last_synced_at":"2025-04-01T04:51:18.567Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/enricopolanski.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-01-11T12:08:10.000Z","updated_at":"2025-03-31T10:56:12.000Z","dependencies_parsed_at":"2024-10-14T12:40:49.764Z","dependency_job_id":"9dc601d0-7a68-4b00-b7a1-92585351c577","html_url":"https://github.com/enricopolanski/functional-programming","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enricopolanski%2Ffunctional-programming","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enricopolanski%2Ffunctional-programming/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enricopolanski%2Ffunctional-programming/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enricopolanski%2Ffunctional-programming/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/enricopolanski","download_url":"https://codeload.github.com/enricopolanski/functional-programming/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247790501,"owners_count":20996539,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T19:01:47.345Z","updated_at":"2025-04-08T06:29:52.076Z","avatar_url":"https://github.com/enricopolanski.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","Articles"],"sub_categories":["Basics"],"readme":"\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n\n  - [Translations](#translations)\n- [What is functional programming](#what-is-functional-programming)\n- [The two pillars of functional programming](#the-two-pillars-of-functional-programming)\n  - [Referential transparency](#referential-transparency)\n  - [Composition](#composition)\n- [Modelling composition with Semigroups](#modelling-composition-with-semigroups)\n  - [Definition of a Magma](#definition-of-a-magma)\n  - [Definition of a Semigroup](#definition-of-a-semigroup)\n  - [The `concatAll` function](#the-concatall-function)\n  - [The dual semigroup](#the-dual-semigroup)\n  - [Semigroup product](#semigroup-product)\n  - [Finding a Semigroup instance for any type](#finding-a-semigroup-instance-for-any-type)\n  - [Order-derivable Semigroups](#order-derivable-semigroups)\n- [Modelling equivalence with `Eq`](#modelling-equivalence-with-eq)\n  - [Modeling ordering relations with `Ord`](#modeling-ordering-relations-with-ord)\n  - [Dual Ordering](#dual-ordering)\n- [Modeling composition through Monoids](#modeling-composition-through-monoids)\n  - [The `concatAll` function](#the-concatall-function-1)\n  - [Product monoid](#product-monoid)\n- [Pure and partial functions](#pure-and-partial-functions)\n- [Algebraic Data Types](#algebraic-data-types)\n  - [What is an ADT?](#what-is-an-adt)\n  - [Product types](#product-types)\n    - [Why \"product\" types?](#why-product-types)\n    - [When can I use a product type?](#when-can-i-use-a-product-type)\n  - [Sum types](#sum-types)\n    - [Constructors](#constructors)\n    - [Pattern matching](#pattern-matching)\n    - [Why \"sum\" types?](#why-sum-types)\n    - [When should I use a sum type?](#when-should-i-use-a-sum-type)\n  - [Functional error handling](#functional-error-handling)\n    - [The `Option` type](#the-option-type)\n    - [An `Eq` instance](#an-eq-instance)\n    - [`Semigroup` and `Monoid` instances](#semigroup-and-monoid-instances)\n    - [The `Either` type](#the-either-type)\n- [Category theory](#category-theory)\n  - [Definition](#definition)\n    - [Part I (Constituents)](#part-i-constituents)\n    - [Part II (Composition)](#part-ii-composition)\n  - [Modeling programming languages with categories](#modeling-programming-languages-with-categories)\n  - [A category for TypeScript](#a-category-for-typescript)\n  - [Composition's core problem](#compositions-core-problem)\n- [Functors](#functors)\n  - [Functions as programs](#functions-as-programs)\n  - [A boundary that leads to functors](#a-boundary-that-leads-to-functors)\n  - [Definition](#definition-1)\n  - [Functors and functional error handling](#functors-and-functional-error-handling)\n  - [Functors compose](#functors-compose)\n  - [Contravariant Functors](#contravariant-functors)\n  - [Functors in `fp-ts`](#functors-in-fp-ts)\n  - [Do functors solve the general problem?](#do-functors-solve-the-general-problem)\n- [Applicative functors](#applicative-functors)\n  - [Currying](#currying)\n  - [The `ap` operation](#the-ap-operation)\n  - [The `of` operation](#the-of-operation)\n  - [Applicative functors compose](#applicative-functors-compose)\n  - [Do applicative functors solve the general problem?](#do-applicative-functors-solve-the-general-problem)\n- [Monads](#monads)\n  - [The problem with nested contexts](#the-problem-with-nested-contexts)\n  - [Monad Definition](#monad-definition)\n  - [The Kleisli category](#the-kleisli-category)\n  - [Defining `chain` step by step](#defining-chain-step-by-step)\n  - [Manipulating programs](#manipulating-programs)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\nThis repo introduces functional programming concepts using TypeScript and possibly libraries in the fp-ts ecosystem.\n\nThis fork is an edited translation of [Giulio Canti](https://gcanti.github.io/about.html)'s [\"Introduction to Functional Programming (Italian)\"](https://github.com/gcanti/functional-programming). The author uses the original as a reference and supporting material for his lectures and workshops on functional programming.\n\nThe purpose of the edits is to expand on the material without changing the concepts nor structure, for more information about the edit's goals see the [CONTRIBUTING](/CONTRIBUTING.md) file.\n\n## Translations\n\n- [Simplified Chinese and Japanese](https://github.com/YiCChi/functional-programming)  by @YiCChi\n\n\n\n# What is functional programming\n\n\u003e Functional Programming is programming with pure functions. Mathematical functions.\n\nA quick search on the internet may lead you to the following definition:\n\n\u003e A (pure) function is a procedure that given the same input always return the same output without any observable side-effect.\n\nThe term \"side effect\" does not yet have any specific meaning (we'll see in the future how to give a formal definition), what matters is to have some sort of intuition, think about opening a file or writing into a database.\n\nFor the time being we can limit ourselves to say that a side effect is _anything_ a function does besides returning a value.\n\nWhat is the structure of a program that uses exclusively pure functions?\n\nA functional program tends to be written like a **pipeline**:\n\n```ts\nconst program = pipe(\n  input,\n  f1, // pure function\n  f2, // pure function\n  f3, // pure function\n  ...\n)\n```\n\nWhat happens here is that `input` is passed to the first function `f1`, which returns a value that is passed to the second function `f2`, which returns a value that is passed as an argument to the third function `f3`, and so on.\n\n**Demo**\n\n[`00_pipe_and_flow.ts`](src/00_pipe_and_flow.ts)\n\nWe'll see how functional programming provides us with tools to structure our code in that style.\n\nOther than understanding what functional programming _is_, it is also essential to understand what is it's goal.\n\nFunctional programming's goal is to **tame a system's complexity** through the use of formal _models_, and to give careful attention to **code's properties** and refactoring ease.\n\n\u003e Functional programming will help teach people the mathematics behind program construction:\n\u003e\n\u003e - how to write composable code\n\u003e - how to reason about side effects\n\u003e - how to write consistent, general, less ad-hoc APIs\n\nWhat does it mean to give careful attention to code's properties? Let's see with an example:\n\n**Example**\n\nWhy can we say that the `Array`'s `map` method is \"more functional\" than a `for` loop?\n\n```ts\n// input\nconst xs: Array\u003cnumber\u003e = [1, 2, 3]\n\n// transformation\nconst double = (n: number): number =\u003e n * 2\n\n// result: I want an array where each `xs`' element is doubled\nconst ys: Array\u003cnumber\u003e = []\nfor (let i = 0; i \u003c= xs.length; i++) {\n  ys.push(double(xs[i]))\n}\n```\n\nA `for` loop offers a lot of flexibility, I can modify:\n\n- the starting index, `let i = 0`\n- the looping condition, `i \u003c xs.length`\n- the step change, `i++`.\n\nThis also implies that I may introduce **errors** and that I have no guarantees about the returned value.\n\n**Quiz**. Is the `for loop` correct?\n\n\u003e See the [answer here](src/quiz-answers/for-loop.md)\n\nLet's rewrite the same exercise using `map`.\n\n```ts\n// input\nconst xs: Array\u003cnumber\u003e = [1, 2, 3]\n\n// transformation\nconst double = (n: number): number =\u003e n * 2\n\n// result: I want an array where each `xs`' element is doubled\nconst ys: Array\u003cnumber\u003e = xs.map(double)\n```\n\nWe can note how `map` lacks the same flexibility of a `for loop`, but it offers us some guarantees:\n\n- all the elements of the input array will be processed\n- the resulting array will always have the same number of elements as the starting one\n\nIn functional programming, where there's an emphasis on code properties rather than implementation details, the `map` operation is interesting **due to its limitations**\n\nThink about how easier it is to review a PR that involves `map` rather than a `for` loop.\n\n# The two pillars of functional programming\n\nFunctional programming is based on the following two pillars:\n\n- Referential transparency\n- Composition (as universal design pattern)\n\nAll of the remaining content derives directly or indirectly from those two points.\n\n## Referential transparency\n\n\u003e **Definition**. An **expression** is said to be _referentially transparent_ if it can be replaced with its corresponding value without changing the program's behavior\n\n**Example** (referential transparency implies the use of pure functions)\n\n```ts\nconst double = (n: number): number =\u003e n * 2\n\nconst x = double(2)\nconst y = double(2)\n```\n\nThe expression `double(2)` has the referential transparency property because it is replaceable with its value, the number 4.\n\nThus I can proceed with the following refactor\n\n```ts\nconst x = 4\nconst y = x\n```\n\nNot every expression is referentially transparent, let's see an example.\n\n**Example** (referential transparency implies not throwing exceptions)\n\n```ts\nconst inverse = (n: number): number =\u003e {\n  if (n === 0) throw new Error('cannot divide by zero')\n  return 1 / n\n}\n\nconst x = inverse(0) + 1\n```\n\nI can't replace `inverse(0)` with its value, thus it is not referentially transparent.\n\n**Example** (referential transparency requires the use of immutable data structures)\n\n```ts\nconst xs = [1, 2, 3]\n\nconst append = (xs: Array\u003cnumber\u003e): void =\u003e {\n  xs.push(4)\n}\n\nappend(xs)\n\nconst ys = xs\n```\n\nOn the last line I cannot replace `xs` with its initial value `[1, 2, 3]` since it has been changed by calling `append`.\n\nWhy is referential transparency so important? Because it allows us to:\n\n- **reason about code locally**, there is no need to know external context in order to understand a fragment of code\n- **refactor** without changing our system's behaviour\n\n**Quiz**. Suppose we have the following program:\n\n```ts\n// In TypeScript `declare` allows to introduce a definition without requiring an implementation\ndeclare const question: (message: string) =\u003e Promise\u003cstring\u003e\n\nconst x = await question('What is your name?')\nconst y = await question('What is your name?')\n```\n\nCan I refactor in this way? Does the program's behavior change or is it going to change?\n\n```ts\nconst x = await question('What is your name?')\nconst y = x\n```\n\nThe answer is: there's no way to know without reading `question`'s _implementation_.\n\nAs you can see, refactoring a program including non-referentially transparent expressions might be challenging.\nIn functional programming, where every expression is referentially transparent, the cognitive load required to make changes is severely reduced.\n\n## Composition\n\nFunctional programming's fundamental pattern is _composition_: we compose small units of code accomplishing very specific tasks into larger and complex units.\n\nAn example of a \"from the smallest to the largest\" composition pattern we can think of:\n\n- composing two or more primitive values (numbers or strings)\n- composing two or more functions\n- composing entire programs\n\nIn the very last example we can speak of _modular programming_:\n\n\u003e By modular programming I mean the process of building large programs by gluing together smaller programs - Simon Peyton Jones\n\nThis programming style is achievable through the use of combinators.\n\nThe term **combinator** refers to the [combinator pattern](https://wiki.haskell.org/Combinator):\n\n\u003e A style of organizing libraries centered around the idea of combining things. Usually there is some type `T`, some \"primitive\" values of type `T`, and some \"combinators\" which can combine values of type `T` in various ways to build up more complex values of type `T`\n\nThe general concept of a combinator is rather vague and it can appear in different forms, but the simplest one is this:\n\n```ts\ncombinator: Thing -\u003e Thing\n```\n\n**Example**. The function `double` combines two numbers.\n\nThe goal of a combinator is to create new *Thing*s from *Thing*s already defined.\n\nSince the output of a combinator, the new _Thing_, can be passed around as input to other programs and combinators, we obtain a combinatorial explosion of opportunities, which makes this pattern extremely powerful.\n\n**Example**\n\n```ts\nimport { pipe } from 'fp-ts/function'\n\nconst double = (n: number): number =\u003e n * 2\n\nconsole.log(pipe(2, double, double, double)) // =\u003e 16\n```\n\nThus the usual design you can find in a functional module is:\n\n- a model for some type `T`\n- a small set of \"primitives\" of type `T`\n- a set of combinators to combine the primitives in larger structures\n\nLet's try to implement such a module:\n\n**Demo**\n\n[`01_retry.ts`](src/01_retry.ts)\n\nAs you can see from the previous demo, with merely 3 primitives and two combinators we've been able to express a pretty complex policy.\n\nThink at how just adding a single new primitive, or a single combinator to those already defined, adds expressive possibilities exponentially.\n\nOf the two combinators in `01_retry.ts` a special mention goes to `concat` since it refers to a very powerful functional programming abstraction: semigroups.\n\n# Modelling composition with Semigroups\n\nA semigroup is a recipe to combine two, or more, values.\n\nA semigroup is an **algebra**, which is generally defined as a specific combination of:\n\n- one or more sets\n- one or more operations on those sets\n- zero or more laws on the previous operations\n\nAlgebras are how mathematicians try to capture an idea in its purest form, eliminating everything that is superfluous.\n\n\u003e When an algebra is modified the only allowed operations are those defined by the algebra itself according to its own laws\n\nAlgebras can be thought of as an abstraction of **interfaces**:\n\n\u003e When an interface is modified the only allowed operations are those defined by the interface itself according to its own laws\n\nBefore getting into semigroups, let's see first an example of an algebra, a _magma_.\n\n## Definition of a Magma\n\nA Magma\u003cA\u003e is a very simple algebra:\n\n- a set or type (A)\n- a `concat` operation\n- no laws to obey\n\n**Note**: in most cases the terms _set_ and _type_ can be used interchangeably.\n\nWe can use a TypeScript `interface` to model a Magma.\n\n```ts\ninterface Magma\u003cA\u003e {\n  readonly concat: (first: A, second: A) =\u003e A\n}\n```\n\nThus, we have have the ingredients for an algebra:\n\n- a set `A`\n- an operation on the set `A`, `concat`. This operation is said to be _closed on_ the set `A` which means that whichever elements `A` we apply the operation on the result will still be an element of `A`. Since the result is still an `A`, it can be used again as an input for `concat` and the operation can be repeated how many times we want. In other words `concat` is a `combinator` for the type `A`.\n\nLet's implement a concrete instance of `Magma\u003cA\u003e` with `A` being the `number` type.\n\n```ts\nimport { Magma } from 'fp-ts/Magma'\n\nconst MagmaSub: Magma\u003cnumber\u003e = {\n  concat: (first, second) =\u003e first - second\n}\n\n// helper\nconst getPipeableConcat = \u003cA\u003e(M: Magma\u003cA\u003e) =\u003e (second: A) =\u003e (first: A): A =\u003e\n  M.concat(first, second)\n\nconst concat = getPipeableConcat(MagmaSub)\n\n// usage example\n\nimport { pipe } from 'fp-ts/function'\n\npipe(10, concat(2), concat(3), concat(1), concat(2), console.log)\n// =\u003e 2\n```\n\n**Quiz**. The fact that `concat` is a _closed_ operation isn't a trivial detail. If `A` is the set of natural numbers (defined as positive integers) instead of the JavaScript number type (a set of positive and negative floats), could we define a `Magma\u003cNatural\u003e` with `concat` implemented like in `MagmaSub`? Can you think of any other `concat` operation on natural numbers for which the `closure` property isn't valid?\n\n\u003e See the [answer here](src/quiz-answers/magma-concat-closed.md)\n\n**Definition**. Given `A` a non empty set and `*` a binary operation _closed on_ (or _internal to_) `A`, then the pair `(A, *)` is called a _magma_.\n\nMagmas do not obey any law, they only have the closure requirement. Let's see an algebra that do requires another law: semigroups.\n\n## Definition of a Semigroup\n\n\u003e Given a `Magma` if the `concat` operation is **associative** then it's a _semigroup_.\n\nThe term \"associative\" means that the equation:\n\n```ts\n(x * y) * z = x * (y * z)\n\n// or\nconcat(concat(a, b), c) = concat(a, concat(b, c))\n```\n\nholds for any `x`, `y`, `z` in `A`.\n\nIn layman terms _associativity_ tells us that we do not have to worry about parentheses in expressions and that we can simply write `x * y * z` (there's no ambiguity).\n\n**Example**\n\nString concatenation benefits from associativity.\n\n```ts\n(\"a\" + \"b\") + \"c\" = \"a\" + (\"b\" + \"c\") = \"abc\"\n```\n\nEvery semigroup is a magma, but not every magma is a semigroup.\n\n\u003ccenter\u003e\n\u003cimg src=\"images/semigroup.png\" width=\"300\" alt=\"Magma vs Semigroup\" /\u003e\n\u003c/center\u003e\n\n**Example**\n\nThe previous `MagmaSub` is not a semigroup because its `concat` operation is not associative.\n\n```ts\nimport { pipe } from 'fp-ts/function'\nimport { Magma } from 'fp-ts/Magma'\n\nconst MagmaSub: Magma\u003cnumber\u003e = {\n  concat: (first, second) =\u003e first - second\n}\n\npipe(MagmaSub.concat(MagmaSub.concat(1, 2), 3), console.log) // =\u003e -4\npipe(MagmaSub.concat(1, MagmaSub.concat(2, 3)), console.log) // =\u003e 2\n```\n\nSemigroups capture the essence of parallelizable operations\n\nIf we know that there is such an operation that follows the associativity law, we can further split a computation into two sub computations, each of them could be further split into sub computations.\n\n```ts\na * b * c * d * e * f * g * h = ((a * b) * (c * d)) * ((e * f) * (g * h))\n```\n\nSub computations can be run in parallel mode.\n\nAs for `Magma`, `Semigroup`s are implemented through a TypeScript `interface`:\n\n```ts\n// fp-ts/lib/Semigroup.ts\n\ninterface Semigroup\u003cA\u003e extends Magma\u003cA\u003e {}\n```\n\nThe following law has to hold true:\n\n- **Associativity**: If `S` is a semigroup the following has to hold true:\n\n```ts\nS.concat(S.concat(x, y), z) = S.concat(x, S.concat(y, z))\n```\n\nfor every `x`, `y`, `z` of type `A`\n\n**Note**. Sadly it is not possible to encode this law using TypeScript's type system.\n\nLet's implement a semigroup for some `ReadonlyArray\u003cstring\u003e`:\n\n```ts\nimport * as Se from 'fp-ts/Semigroup'\n\nconst Semigroup: Se.Semigroup\u003cReadonlyArray\u003cstring\u003e\u003e = {\n  concat: (first, second) =\u003e first.concat(second)\n}\n```\n\nThe name `concat` makes sense for arrays (as we'll see later) but, depending on the context and the type `A` on whom we're implementing an instance, the `concat` semigroup operation may have different interpretations and meanings:\n\n- \"concatenation\"\n- \"combination\"\n- \"merging\"\n- \"fusion\"\n- \"selection\"\n- \"sum\"\n- \"substitution\"\n\nand many others.\n\n**Example**\n\nThis is how to implement the semigroup `(number, +)` where `+` is the usual addition of numbers:\n\n```ts\nimport { Semigroup } from 'fp-ts/Semigroup'\n\n/** number `Semigroup` under addition */\nconst SemigroupSum: Semigroup\u003cnumber\u003e = {\n  concat: (first, second) =\u003e first + second\n}\n```\n\n**Quiz**. Can the `concat` combinator defined in the demo [`01_retry.ts`](src/01_retry.ts) be used to define a `Semigroup` instance for the `RetryPolicy` type?\n\n\u003e See the [answer here](src/quiz-answers/semigroup-demo-concat.md)\n\nThis is the implementation for the semigroup `(number, *)` where `*` is the usual number multiplication:\n\n```ts\nimport { Semigroup } from 'fp-ts/Semigroup'\n\n/** number `Semigroup` under multiplication */\nconst SemigroupProduct: Semigroup\u003cnumber\u003e = {\n  concat: (first, second) =\u003e first * second\n}\n```\n\n**Note** It is a common mistake to think about the _semigroup of numbers_, but for the same type `A` it is possible to define more **instances** of `Semigroup\u003cA\u003e`. We've seen how for `number` we can define a semigroup under _addition_ and _multiplication_. It is also possible to have `Semigroup`s that share the same operation but differ in types. `SemigroupSum` could've been implemented on natural numbers instead of unsigned floats like `number`.\n\nAnother example, with the `string` type:\n\n```ts\nimport { Semigroup } from 'fp-ts/Semigroup'\n\nconst SemigroupString: Semigroup\u003cstring\u003e = {\n  concat: (first, second) =\u003e first + second\n}\n```\n\nAnother two examples, this time with the `boolean` type:\n\n```ts\nimport { Semigroup } from 'fp-ts/Semigroup'\n\nconst SemigroupAll: Semigroup\u003cboolean\u003e = {\n  concat: (first, second) =\u003e first \u0026\u0026 second\n}\n\nconst SemigroupAny: Semigroup\u003cboolean\u003e = {\n  concat: (first, second) =\u003e first || second\n}\n```\n\n## The `concatAll` function\n\nBy definition `concat` combines merely two elements of `A` every time. Is it possible to combine any number of them?\n\nThe `concatAll` function takes:\n\n- an instance of a semigroup\n- an initial value\n- an array of elements\n\n```ts\nimport * as S from 'fp-ts/Semigroup'\nimport * as N from 'fp-ts/number'\n\nconst sum = S.concatAll(N.SemigroupSum)(2)\n\nconsole.log(sum([1, 2, 3, 4])) // =\u003e 12\n\nconst product = S.concatAll(N.SemigroupProduct)(3)\n\nconsole.log(product([1, 2, 3, 4])) // =\u003e 72\n```\n\n**Quiz**. Why do I need to provide an initial value?\n\n-\u003e See the [answer here](src/quiz-answers/semigroup-concatAll-initial-value.md)\n\n**Example**\n\nLets provide some applications of `concatAll`, by reimplementing some popular functions from the JavaScript standard library.\n\n```ts\nimport * as B from 'fp-ts/boolean'\nimport { concatAll } from 'fp-ts/Semigroup'\nimport * as S from 'fp-ts/struct'\n\nconst every = \u003cA\u003e(predicate: (a: A) =\u003e boolean) =\u003e (\n  as: ReadonlyArray\u003cA\u003e\n): boolean =\u003e concatAll(B.SemigroupAll)(true)(as.map(predicate))\n\nconst some = \u003cA\u003e(predicate: (a: A) =\u003e boolean) =\u003e (\n  as: ReadonlyArray\u003cA\u003e\n): boolean =\u003e concatAll(B.SemigroupAny)(false)(as.map(predicate))\n\nconst assign: (as: ReadonlyArray\u003cobject\u003e) =\u003e object = concatAll(\n  S.getAssignSemigroup\u003cobject\u003e()\n)({})\n```\n\n**Quiz**. Is the following semigroup instance lawful (does it respect semigroup laws)?\n\n\u003e See the [answer here](src/quiz-answers/semigroup-first.md)\n\n```ts\nimport { Semigroup } from 'fp-ts/Semigroup'\n\n/** Always return the first argument */\nconst first = \u003cA\u003e(): Semigroup\u003cA\u003e =\u003e ({\n  concat: (first, _second) =\u003e first\n})\n```\n\n**Quiz**. Is the following semigroup instance lawful?\n\n\u003e See the [answer here](src/quiz-answers/semigroup-second.md)\n\n```ts\nimport { Semigroup } from 'fp-ts/Semigroup'\n\n/** Always return the second argument */\nconst last = \u003cA\u003e(): Semigroup\u003cA\u003e =\u003e ({\n  concat: (_first, second) =\u003e second\n})\n```\n\n## The dual semigroup\n\nGiven a semigroup instance, it is possible to obtain a new semigroup instance by simply swapping the order in which the operands are combined:\n\n```ts\nimport { pipe } from 'fp-ts/function'\nimport { Semigroup } from 'fp-ts/Semigroup'\nimport * as S from 'fp-ts/string'\n\n// This is a Semigroup combinator\nconst reverse = \u003cA\u003e(S: Semigroup\u003cA\u003e): Semigroup\u003cA\u003e =\u003e ({\n  concat: (first, second) =\u003e S.concat(second, first)\n})\n\npipe(S.Semigroup.concat('a', 'b'), console.log) // =\u003e 'ab'\npipe(reverse(S.Semigroup).concat('a', 'b'), console.log) // =\u003e 'ba'\n```\n\n**Quiz**. This combinator makes sense because, generally speaking, the `concat` operation is not [**commutative**](https://en.wikipedia.org/wiki/Commutative_property), can you find an example where `concat` is commutative and one where it isn't?\n\n\u003e See the [answer here](src/quiz-answers/semigroup-commutative.md)\n\n## Semigroup product\n\nLet's try defining a semigroup instance for more complex types:\n\n```ts\nimport * as N from 'fp-ts/number'\nimport { Semigroup } from 'fp-ts/Semigroup'\n\n// models a vector starting at the origin\ntype Vector = {\n  readonly x: number\n  readonly y: number\n}\n\n// models a sum of two vectors\nconst SemigroupVector: Semigroup\u003cVector\u003e = {\n  concat: (first, second) =\u003e ({\n    x: N.SemigroupSum.concat(first.x, second.x),\n    y: N.SemigroupSum.concat(first.y, second.y)\n  })\n}\n```\n\n**Example**\n\n```ts\nconst v1: Vector = { x: 1, y: 1 }\nconst v2: Vector = { x: 1, y: 2 }\n\nconsole.log(SemigroupVector.concat(v1, v2)) // =\u003e { x: 2, y: 3 }\n```\n\n\u003ccenter\u003e\n\u003cimg src=\"images/semigroupVector.png\" width=\"300\" alt=\"SemigroupVector\" /\u003e\n\u003c/center\u003e\n\nToo much boilerplate? The good news is that the **mathematical theory** behind semigroups tells us we can implement a semigroup instance for a struct like `Vector` if we can implement a semigroup instance for each of its fields.\n\nConveniently the `fp-ts/Semigroup` module exports a `struct` combinator:\n\n```ts\nimport { struct } from 'fp-ts/Semigroup'\n\n// models the sum of two vectors\nconst SemigroupVector: Semigroup\u003cVector\u003e = struct({\n  x: N.SemigroupSum,\n  y: N.SemigroupSum\n})\n```\n\n**Note**. There is a combinator similar to `struct` that works with tuples: `tuple`\n\n```ts\nimport * as N from 'fp-ts/number'\nimport { Semigroup, tuple } from 'fp-ts/Semigroup'\n\n// models a vector starting from origin\ntype Vector = readonly [number, number]\n\n// models the sum of two vectors\nconst SemigroupVector: Semigroup\u003cVector\u003e = tuple(N.SemigroupSum, N.SemigroupSum)\n\nconst v1: Vector = [1, 1]\nconst v2: Vector = [1, 2]\n\nconsole.log(SemigroupVector.concat(v1, v2)) // =\u003e [2, 3]\n```\n\n**Quiz**. Is it true that given any `Semigroup\u003cA\u003e` and having chosen any `middle` of `A`, if I insert it between the two `concat` parameters the result is still a semigroup?\n\n```ts\nimport { pipe } from 'fp-ts/function'\nimport { Semigroup } from 'fp-ts/Semigroup'\nimport * as S from 'fp-ts/string'\n\nexport const intercalate = \u003cA\u003e(middle: A) =\u003e (\n  S: Semigroup\u003cA\u003e\n): Semigroup\u003cA\u003e =\u003e ({\n  concat: (first, second) =\u003e S.concat(S.concat(first, middle), second)\n})\n\nconst SemigroupIntercalate = pipe(S.Semigroup, intercalate('|'))\n\npipe(\n  SemigroupIntercalate.concat('a', SemigroupIntercalate.concat('b', 'c')),\n  console.log\n) // =\u003e 'a|b|c'\n```\n\n## Finding a Semigroup instance for any type\n\nThe associativity property is a very strong requirement, what happens if, given a specific type `A` we can't find an associative operation on `A`?\n\nSuppose we have a type `User` defined as:\n\n```ts\ntype User = {\n  readonly id: number\n  readonly name: string\n}\n```\n\nand that inside my database we have multiple copies of the same `User` (e.g. they could be historical entries of its modifications).\n\n```ts\n// internal APIs\ndeclare const getCurrent: (id: number) =\u003e User\ndeclare const getHistory: (id: number) =\u003e ReadonlyArray\u003cUser\u003e\n```\n\nand that we need to implement a public API\n\n```ts\nexport declare const getUser: (id: number) =\u003e User\n```\n\nwhich takes into account all of its copies depending on some criteria. The criteria should be to return the most recent copy, or the oldest one, or the current one, etc..\n\nNaturally we can define a specific API for each of these criterias:\n\n```ts\nexport declare const getMostRecentUser: (id: number) =\u003e User\nexport declare const getLeastRecentUser: (id: number) =\u003e User\nexport declare const getCurrentUser: (id: number) =\u003e User\n// etc...\n```\n\nThus, to return a value of type `User` I need to consider all the copies and make a `merge` (or `selection`) of them, meaning I can model the criteria problem with a `Semigroup\u003cUser\u003e`.\n\nThat being said, it is not really clear right now what it means to \"merge two `User`s\" nor if this merge operation is associative.\n\nYou can **always** define a Semigroup instance for **any** given type `A` by defining a semigroup instance not for `A` itself but for `NonEmptyArray\u003cA\u003e` called the **free semigroup** of `A`:\n\n```ts\nimport { Semigroup } from 'fp-ts/Semigroup'\n\n// represents a non-empty array, meaning an array that has at least one element A\ntype ReadonlyNonEmptyArray\u003cA\u003e = ReadonlyArray\u003cA\u003e \u0026 {\n  readonly 0: A\n}\n\n// the concatenation of two NonEmptyArrays is still a NonEmptyArray\nconst getSemigroup = \u003cA\u003e(): Semigroup\u003cReadonlyNonEmptyArray\u003cA\u003e\u003e =\u003e ({\n  concat: (first, second) =\u003e [first[0], ...first.slice(1), ...second]\n})\n```\n\nand then we can map the elements of `A` to \"singletons\" of `ReadonlyNonEmptyArray\u003cA\u003e`, meaning arrays with only one element.\n\n```ts\n// insert an element into a non empty array\nconst of = \u003cA\u003e(a: A): ReadonlyNonEmptyArray\u003cA\u003e =\u003e [a]\n```\n\nLet's apply this technique to the `User` type:\n\n```ts\nimport {\n  getSemigroup,\n  of,\n  ReadonlyNonEmptyArray\n} from 'fp-ts/ReadonlyNonEmptyArray'\nimport { Semigroup } from 'fp-ts/Semigroup'\n\ntype User = {\n  readonly id: number\n  readonly name: string\n}\n\n// this semigroup is not for the `User` type but for `ReadonlyNonEmptyArray\u003cUser\u003e`\nconst S: Semigroup\u003cReadonlyNonEmptyArray\u003cUser\u003e\u003e = getSemigroup\u003cUser\u003e()\n\ndeclare const user1: User\ndeclare const user2: User\ndeclare const user3: User\n\n// const merge: ReadonlyNonEmptyArray\u003cUser\u003e\nconst merge = S.concat(S.concat(of(user1), of(user2)), of(user3))\n\n// I can get the same result by \"packing\" the users manually into an array\nconst merge2: ReadonlyNonEmptyArray\u003cUser\u003e = [user1, user2, user3]\n```\n\nThus, the free semigroup of `A` is merely another semigroup in which the elements are all possible, non empty, finite sequences of `A`.\n\nThe free semigroup of `A` can be seen as a _lazy_ way to `concat`enate elements of type `A` while preserving their data content.\n\nThe `merge` value, containing `[user1, user2, user3]`, tells us which are the elements to concatenate and in which order they are.\n\nNow I have three possible options to design the `getUser` API:\n\n1. I can define `Semigroup\u003cUser\u003e` and I want to get straight into `merge`ing.\n\n```ts\ndeclare const SemigroupUser: Semigroup\u003cUser\u003e\n\nexport const getUser = (id: number): User =\u003e {\n  const current = getCurrent(id)\n  const history = getHistory(id)\n  return concatAll(SemigroupUser)(current)(history)\n}\n```\n\n2. I can't define `Semigroup\u003cUser\u003e` or I want to leave the merging strategy open to implementation, thus I'll ask it to the API consumer:\n\n```ts\nexport const getUser = (SemigroupUser: Semigroup\u003cUser\u003e) =\u003e (\n  id: number\n): User =\u003e {\n  const current = getCurrent(id)\n  const history = getHistory(id)\n  // merge immediately\n  return concatAll(SemigroupUser)(current)(history)\n}\n```\n\n3. I can't define `Semigroup\u003cUser\u003e` nor I want to require it.\n\nIn this case the free semigroup of `User` can come to the rescue:\n\n```ts\nexport const getUser = (id: number): ReadonlyNonEmptyArray\u003cUser\u003e =\u003e {\n  const current = getCurrent(id)\n  const history = getHistory(id)\n  // I DO NOT proceed with merging and return the free semigroup of User\n  return [current, ...history]\n}\n```\n\nIt should be noted that, even when I do have a `Semigroup\u003cA\u003e` instance, using a free semigroup might be still convenient for the following reasons:\n\n- avoids executing possibly expensive and pointless computations\n- avoids passing around the semigroup instance\n- allows the API consumer to decide which is the correct merging strategy (by using `concatAll`).\n\n## Order-derivable Semigroups\n\nGiven that `number` is **a total order** (meaning that whichever `x` and `y` we choose, one of those two conditions has to hold true: `x \u003c= y` or `y \u003c= x`) we can define another two `Semigroup\u003cnumber\u003e` instances using the `min` or `max` operations.\n\n```ts\nimport { Semigroup } from 'fp-ts/Semigroup'\n\nconst SemigroupMin: Semigroup\u003cnumber\u003e = {\n  concat: (first, second) =\u003e Math.min(first, second)\n}\n\nconst SemigroupMax: Semigroup\u003cnumber\u003e = {\n  concat: (first, second) =\u003e Math.max(first, second)\n}\n```\n\n**Quiz**. Why is it so important that `number` is a _total_ order?\n\nIt would be very useful to define such semigroups (`SemigroupMin` and `SemigroupMax`) for different types than `number`.\n\nIs it possible to capture the notion of being _totally ordered_ for other types?\n\nTo speak about _ordering_ we first need to capture the notion of _equality_.\n\n# Modelling equivalence with `Eq`\n\nYet again, we can model the notion of equality.\n\n_Equivalence relations_ capture the concept of _equality_ of elements of the same type. The concept of an _equivalence relation_ can be implemented in TypeScript with the following interface:\n\n```ts\ninterface Eq\u003cA\u003e {\n  readonly equals: (first: A, second: A) =\u003e boolean\n}\n```\n\nIntuitively:\n\n- if `equals(x, y) = true` then we say `x` and `y` are equal\n- if `equals(x, y) = false` then we say `x` and `y` are different\n\n**Example**\n\nThis is an instance of `Eq` for the `number` type:\n\n```ts\nimport { Eq } from 'fp-ts/Eq'\nimport { pipe } from 'fp-ts/function'\n\nconst EqNumber: Eq\u003cnumber\u003e = {\n  equals: (first, second) =\u003e first === second\n}\n\npipe(EqNumber.equals(1, 1), console.log) // =\u003e true\npipe(EqNumber.equals(1, 2), console.log) // =\u003e false\n```\n\nThe following laws have to hold true:\n\n1. **Reflexivity**: `equals(x, x) === true`, for every `x` in `A`\n2. **Symmetry**: `equals(x, y) === equals(y, x)`, for every `x`, `y` in `A`\n3. **Transitivity**: if `equals(x, y) === true` and `equals(y, z) === true`, then `equals(x, z) === true`, for every `x`, `y`, `z` in `A`\n\n**Quiz**. Would a combinator `reverse: \u003cA\u003e(E: Eq\u003cA\u003e) =\u003e Eq\u003cA\u003e` make sense?\n\n**Quiz**. Would a combinator `not: \u003cA\u003e(E: Eq\u003cA\u003e) =\u003e Eq\u003cA\u003e` make sense?\n\n```ts\nimport { Eq } from 'fp-ts/Eq'\n\nexport const not = \u003cA\u003e(E: Eq\u003cA\u003e): Eq\u003cA\u003e =\u003e ({\n  equals: (first, second) =\u003e !E.equals(first, second)\n})\n```\n\n**Example**\n\nLet's see the first example of the usage of the `Eq` abstraction by defining a function `elem` that checks whether a given value is an element of `ReadonlyArray`.\n\n```ts\nimport { Eq } from 'fp-ts/Eq'\nimport { pipe } from 'fp-ts/function'\nimport * as N from 'fp-ts/number'\n\n// returns `true` if the element `a` is included in the list `as`\nconst elem = \u003cA\u003e(E: Eq\u003cA\u003e) =\u003e (a: A) =\u003e (as: ReadonlyArray\u003cA\u003e): boolean =\u003e\n  as.some((e) =\u003e E.equals(a, e))\n\npipe([1, 2, 3], elem(N.Eq)(2), console.log) // =\u003e true\npipe([1, 2, 3], elem(N.Eq)(4), console.log) // =\u003e false\n```\n\nWhy would we not use the native `includes` Array method?\n\n```ts\nconsole.log([1, 2, 3].includes(2)) // =\u003e true\nconsole.log([1, 2, 3].includes(4)) // =\u003e false\n```\n\nLet's define some `Eq` instance for more complex types.\n\n```ts\nimport { Eq } from 'fp-ts/Eq'\n\ntype Point = {\n  readonly x: number\n  readonly y: number\n}\n\nconst EqPoint: Eq\u003cPoint\u003e = {\n  equals: (first, second) =\u003e first.x === second.x \u0026\u0026 first.y === second.y\n}\n\nconsole.log(EqPoint.equals({ x: 1, y: 2 }, { x: 1, y: 2 })) // =\u003e true\nconsole.log(EqPoint.equals({ x: 1, y: 2 }, { x: 1, y: -2 })) // =\u003e false\n```\n\nand check the results of `elem` and `includes`\n\n```ts\nconst points: ReadonlyArray\u003cPoint\u003e = [\n  { x: 0, y: 0 },\n  { x: 1, y: 1 },\n  { x: 2, y: 2 }\n]\n\nconst search: Point = { x: 1, y: 1 }\n\nconsole.log(points.includes(search)) // =\u003e false :(\nconsole.log(pipe(points, elem(EqPoint)(search))) // =\u003e true :)\n```\n\n**Quiz** (JavaScript). Why does the `includes` method returns `false`?\n\n-\u003e See the [answer here](src/quiz-answers/javascript-includes.md)\n\nAbstracting the concept of equality is of paramount importance, especially in a language like JavaScript where some data types do not offer handy APIs for checking user-defined equality.\n\nThe JavaScript native `Set` datatype suffers by the same issue:\n\n```ts\ntype Point = {\n  readonly x: number\n  readonly y: number\n}\n\nconst points: Set\u003cPoint\u003e = new Set([{ x: 0, y: 0 }])\n\npoints.add({ x: 0, y: 0 })\n\nconsole.log(points)\n// =\u003e Set { { x: 0, y: 0 }, { x: 0, y: 0 } }\n```\n\nGiven the fact that `Set` uses `===` (\"strict equality\") for comparing values, `points` now contains **two identical copies** of `{ x: 0, y: 0 }`, a result we definitely did not want. Thus it is convenient to define a new API to add an element to a `Set`, one that leverages the `Eq` abstraction.\n\n**Quiz**. What would be the signature of this API?\n\nDoes `EqPoint` require too much boilerplate? The good news is that theory offers us yet again the possibility of implementing an `Eq` instance for a struct like `Point` if we are able to define an `Eq` instance for each of its fields.\n\nConveniently the `fp-ts/Eq` module exports a `struct` combinator:\n\n```ts\nimport { Eq, struct } from 'fp-ts/Eq'\nimport * as N from 'fp-ts/number'\n\ntype Point = {\n  readonly x: number\n  readonly y: number\n}\n\nconst EqPoint: Eq\u003cPoint\u003e = struct({\n  x: N.Eq,\n  y: N.Eq\n})\n```\n\n**Note**. Like for Semigroup, we aren't limited to `struct`-like data types, we also have combinators for working with tuples: `tuple`\n\n```ts\nimport { Eq, tuple } from 'fp-ts/Eq'\nimport * as N from 'fp-ts/number'\n\ntype Point = readonly [number, number]\n\nconst EqPoint: Eq\u003cPoint\u003e = tuple(N.Eq, N.Eq)\n\nconsole.log(EqPoint.equals([1, 2], [1, 2])) // =\u003e true\nconsole.log(EqPoint.equals([1, 2], [1, -2])) // =\u003e false\n```\n\nThere are other combinators exported by `fp-ts`, here we can see a combinator that allows us to derive an `Eq` instance for `ReadonlyArray`s.\n\n```ts\nimport { Eq, tuple } from 'fp-ts/Eq'\nimport * as N from 'fp-ts/number'\nimport * as RA from 'fp-ts/ReadonlyArray'\n\ntype Point = readonly [number, number]\n\nconst EqPoint: Eq\u003cPoint\u003e = tuple(N.Eq, N.Eq)\n\nconst EqPoints: Eq\u003cReadonlyArray\u003cPoint\u003e\u003e = RA.getEq(EqPoint)\n```\n\nSimilarly to Semigroups, it is possible to define more than one `Eq` instance for the same given type. Suppose we have modeled a `User` with the following type:\n\n```ts\ntype User = {\n  readonly id: number\n  readonly name: string\n}\n```\n\nwe can define a \"standard\" `Eq\u003cUser\u003e` instance using the `struct` combinator:\n\n```ts\nimport { Eq, struct } from 'fp-ts/Eq'\nimport * as N from 'fp-ts/number'\nimport * as S from 'fp-ts/string'\n\ntype User = {\n  readonly id: number\n  readonly name: string\n}\n\nconst EqStandard: Eq\u003cUser\u003e = struct({\n  id: N.Eq,\n  name: S.Eq\n})\n```\n\nSeveral languages, even pure functional languages like Haskell, do not allow to have more than one `Eq` instance per data type. But we may have different contexts where the meaning of `User` equality might differ. One common context is where two `User`s are equal if their `id` field is equal.\n\n```ts\n/** two users are equal if their `id` fields are equal */\nconst EqID: Eq\u003cUser\u003e = {\n  equals: (first, second) =\u003e N.Eq.equals(first.id, second.id)\n}\n```\n\nNow that we made an abstract concept concrete by representing it as a data structure, we can programmatically manipulate `Eq` instances like we do with other data structures. Let's see an example.\n\n**Example**. Rather than manually defining `EqId` we can use the combinator `contramap`: given an instance `Eq\u003cA\u003e` and a function from `B` to `A`, we can derive an `Eq\u003cB\u003e`\n\n```ts\nimport { Eq, struct, contramap } from 'fp-ts/Eq'\nimport { pipe } from 'fp-ts/function'\nimport * as N from 'fp-ts/number'\nimport * as S from 'fp-ts/string'\n\ntype User = {\n  readonly id: number\n  readonly name: string\n}\n\nconst EqStandard: Eq\u003cUser\u003e = struct({\n  id: N.Eq,\n  name: S.Eq\n})\n\nconst EqID: Eq\u003cUser\u003e = pipe(\n  N.Eq,\n  contramap((user: User) =\u003e user.id)\n)\n\nconsole.log(\n  EqStandard.equals({ id: 1, name: 'Giulio' }, { id: 1, name: 'Giulio Canti' })\n) // =\u003e false (because the `name` property differs)\n\nconsole.log(\n  EqID.equals({ id: 1, name: 'Giulio' }, { id: 1, name: 'Giulio Canti' })\n) // =\u003e true (even though the `name` property differs)\n\nconsole.log(EqID.equals({ id: 1, name: 'Giulio' }, { id: 2, name: 'Giulio' }))\n// =\u003e false (even though the `name` property is equal)\n```\n\n**Quiz**. Given a data type `A`, is it possible to define a `Semigroup\u003cEq\u003cA\u003e\u003e`? What could it represent?\n\n## Modeling ordering relations with `Ord`\n\nIn the previous chapter regarding `Eq` we were dealing with the concept of **equality**. In this one we'll deal with the concept of **ordering**.\n\nThe concept of a total order relation can be implemented in TypeScript as following:\n\n```ts\nimport { Eq } from 'fp-ts/lib/Eq'\n\ntype Ordering = -1 | 0 | 1\n\ninterface Ord\u003cA\u003e extends Eq\u003cA\u003e {\n  readonly compare: (x: A, y: A) =\u003e Ordering\n}\n```\n\nResulting in:\n\n- `x \u003c y` if and only if `compare(x, y) = -1`\n- `x = y` if and only if `compare(x, y) = 0`\n- `x \u003e y` if and only if `compare(x, y) = 1`\n\n**Example**\n\nLet's try to define an `Ord` instance for the type `number`:\n\n```ts\nimport { Ord } from 'fp-ts/Ord'\n\nconst OrdNumber: Ord\u003cnumber\u003e = {\n  equals: (first, second) =\u003e first === second,\n  compare: (first, second) =\u003e (first \u003c second ? -1 : first \u003e second ? 1 : 0)\n}\n```\n\nThe following laws have to hold true:\n\n1. **Reflexivity**: `compare(x, x) \u003c= 0`, for every `x` in `A`\n2. **Antisymmetry**: if `compare(x, y) \u003c= 0` and `compare(y, x) \u003c= 0` then `x = y`, for every `x`, `y` in `A`\n3. **Transitivity**: if `compare(x, y) \u003c= 0` and `compare(y, z) \u003c= 0` then `compare(x, z) \u003c= 0`, for every `x`, `y`, `z` in `A`\n\n`compare` has also to be compatible with the `equals` operation from `Eq`:\n\n`compare(x, y) === 0` if and only if `equals(x, y) === true`, for every `x`, `y` in `A`\n\n**Note**. `equals` can be derived from `compare` in the following way:\n\n```ts\nequals: (first, second) =\u003e compare(first, second) === 0\n```\n\nIn fact the `fp-ts/Ord` module exports a handy helper `fromCompare` which allows us to define an `Ord` instance simply by supplying the `compare` function:\n\n```ts\nimport { Ord, fromCompare } from 'fp-ts/Ord'\n\nconst OrdNumber: Ord\u003cnumber\u003e = fromCompare((first, second) =\u003e\n  first \u003c second ? -1 : first \u003e second ? 1 : 0\n)\n```\n\n**Quiz**. Is it possible to define an `Ord` instance for the game Rock-Paper-Scissor where `move1 \u003c= move2` if `move2` beats `move1`?\n\nLet's see a practical usage of an `Ord` instance by defining a `sort` function which orders the elements of a `ReadonlyArray`.\n\n```ts\nimport { pipe } from 'fp-ts/function'\nimport * as N from 'fp-ts/number'\nimport { Ord } from 'fp-ts/Ord'\n\nexport const sort = \u003cA\u003e(O: Ord\u003cA\u003e) =\u003e (\n  as: ReadonlyArray\u003cA\u003e\n): ReadonlyArray\u003cA\u003e =\u003e as.slice().sort(O.compare)\n\npipe([3, 1, 2], sort(N.Ord), console.log) // =\u003e [1, 2, 3]\n```\n\n**Quiz** (JavaScript). Why does the implementation leverages the native Array `slice` method?\n\nLet's see another `Ord` pratical usage by defining a `min` function that returns the smallest of two values:\n\n```ts\nimport { pipe } from 'fp-ts/function'\nimport * as N from 'fp-ts/number'\nimport { Ord } from 'fp-ts/Ord'\n\nconst min = \u003cA\u003e(O: Ord\u003cA\u003e) =\u003e (second: A) =\u003e (first: A): A =\u003e\n  O.compare(first, second) === 1 ? second : first\n\npipe(2, min(N.Ord)(1), console.log) // =\u003e 1\n```\n\n## Dual Ordering\n\nIn the same way we could invert the `concat` operation to obtain the `dual semigroup` using the `reverse` combinator, we can invert the `compare` operation to get the dual ordering.\n\nLet's define the `reverse` combinator for `Ord`:\n\n```ts\nimport { pipe } from 'fp-ts/function'\nimport * as N from 'fp-ts/number'\nimport { fromCompare, Ord } from 'fp-ts/Ord'\n\nexport const reverse = \u003cA\u003e(O: Ord\u003cA\u003e): Ord\u003cA\u003e =\u003e\n  fromCompare((first, second) =\u003e O.compare(second, first))\n```\n\nA usage example for `reverse` is obtaining a `max` function from the `min` one:\n\n```ts\nimport { flow, pipe } from 'fp-ts/function'\nimport * as N from 'fp-ts/number'\nimport { Ord, reverse } from 'fp-ts/Ord'\n\nconst min = \u003cA\u003e(O: Ord\u003cA\u003e) =\u003e (second: A) =\u003e (first: A): A =\u003e\n  O.compare(first, second) === 1 ? second : first\n\n// const max: \u003cA\u003e(O: Ord\u003cA\u003e) =\u003e (second: A) =\u003e (first: A) =\u003e A\nconst max = flow(reverse, min)\n\npipe(2, max(N.Ord)(1), console.log) // =\u003e 2\n```\n\nThe **totality** of ordering (meaning that given any `x` and `y`, one of the two conditions needs to hold true: `x \u003c= y` or `y \u003c= z`) may appear obvious when speaking about numbers, but that's not always the case. Let's see a slightly more complex scenario:\n\n```ts\ntype User = {\n  readonly name: string\n  readonly age: number\n}\n```\n\nIt's not really clear when a `User` is \"smaller or equal\" than another `User`.\n\nHow can we define an `Ord\u003cUser\u003e` instance?\n\nThat depends on the context, but a possible choice might be ordering `User`s by their age:\n\n```ts\nimport * as N from 'fp-ts/number'\nimport { fromCompare, Ord } from 'fp-ts/Ord'\n\ntype User = {\n  readonly name: string\n  readonly age: number\n}\n\nconst byAge: Ord\u003cUser\u003e = fromCompare((first, second) =\u003e\n  N.Ord.compare(first.age, second.age)\n)\n```\n\nAgain we can get rid of some boilerplate using the `contramap` combinatorL given an `Ord\u003cA\u003e` instance and a function from `B` to `A`, it is possible to derive `Ord\u003cB\u003e`:\n\n```ts\nimport { pipe } from 'fp-ts/function'\nimport * as N from 'fp-ts/number'\nimport { contramap, Ord } from 'fp-ts/Ord'\n\ntype User = {\n  readonly name: string\n  readonly age: number\n}\n\nconst byAge: Ord\u003cUser\u003e = pipe(\n  N.Ord,\n  contramap((_: User) =\u003e _.age)\n)\n```\n\nWe can get the youngest of two `User`s using the previously defined `min` function.\n\n```ts\n// const getYounger: (second: User) =\u003e (first: User) =\u003e User\nconst getYounger = min(byAge)\n\npipe(\n  { name: 'Guido', age: 50 },\n  getYounger({ name: 'Giulio', age: 47 }),\n  console.log\n) // =\u003e { name: 'Giulio', age: 47 }\n```\n\n**Quiz**. In the `fp-ts/ReadonlyMap` module the following API is exposed:\n\n```ts\n/**\n * Get a sorted `ReadonlyArray` of the keys contained in a `ReadonlyMap`.\n */\ndeclare const keys: \u003cK\u003e(\n  O: Ord\u003cK\u003e\n) =\u003e \u003cA\u003e(m: ReadonlyMap\u003cK, A\u003e) =\u003e ReadonlyArray\u003cK\u003e\n```\n\nwhy does this API requires an instance for `Ord\u003cK\u003e`?\n\nLet's finally go back to the very first issue: defining two semigroups `SemigroupMin` and `SemigroupMax` for types different than `number`:\n\n```ts\nimport { Semigroup } from 'fp-ts/Semigroup'\n\nconst SemigroupMin: Semigroup\u003cnumber\u003e = {\n  concat: (first, second) =\u003e Math.min(first, second)\n}\n\nconst SemigroupMax: Semigroup\u003cnumber\u003e = {\n  concat: (first, second) =\u003e Math.max(first, second)\n}\n```\n\nNow that we have the `Ord` abstraction we can do it:\n\n```ts\nimport { pipe } from 'fp-ts/function'\nimport * as N from 'fp-ts/number'\nimport { Ord, contramap } from 'fp-ts/Ord'\nimport { Semigroup } from 'fp-ts/Semigroup'\n\nexport const min = \u003cA\u003e(O: Ord\u003cA\u003e): Semigroup\u003cA\u003e =\u003e ({\n  concat: (first, second) =\u003e (O.compare(first, second) === 1 ? second : first)\n})\n\nexport const max = \u003cA\u003e(O: Ord\u003cA\u003e): Semigroup\u003cA\u003e =\u003e ({\n  concat: (first, second) =\u003e (O.compare(first, second) === 1 ? first : second)\n})\n\ntype User = {\n  readonly name: string\n  readonly age: number\n}\n\nconst byAge: Ord\u003cUser\u003e = pipe(\n  N.Ord,\n  contramap((_: User) =\u003e _.age)\n)\n\nconsole.log(\n  min(byAge).concat({ name: 'Guido', age: 50 }, { name: 'Giulio', age: 47 })\n) // =\u003e { name: 'Giulio', age: 47 }\nconsole.log(\n  max(byAge).concat({ name: 'Guido', age: 50 }, { name: 'Giulio', age: 47 })\n) // =\u003e { name: 'Guido', age: 50 }\n```\n\n**Example**\n\nLet's recap all of this with one final example (adapted from [Fantas, Eel, and Specification 4: Semigroup](http://www.tomharding.me/2017/03/13/fantas-eel-and-specification-4/)).\n\nSuppose we need to build a system where, in a database, there are records of customers implemented in the following way:\n\n```ts\ninterface Customer {\n  readonly name: string\n  readonly favouriteThings: ReadonlyArray\u003cstring\u003e\n  readonly registeredAt: number // since epoch\n  readonly lastUpdatedAt: number // since epoch\n  readonly hasMadePurchase: boolean\n}\n```\n\nFor some reason, there might be duplicate records for the same person.\n\nWe need a merging strategy. Well, that's Semigroup's bread and butter!\n\n```ts\nimport * as B from 'fp-ts/boolean'\nimport { pipe } from 'fp-ts/function'\nimport * as N from 'fp-ts/number'\nimport { contramap } from 'fp-ts/Ord'\nimport * as RA from 'fp-ts/ReadonlyArray'\nimport { max, min, Semigroup, struct } from 'fp-ts/Semigroup'\nimport * as S from 'fp-ts/string'\n\ninterface Customer {\n  readonly name: string\n  readonly favouriteThings: ReadonlyArray\u003cstring\u003e\n  readonly registeredAt: number // since epoch\n  readonly lastUpdatedAt: number // since epoch\n  readonly hasMadePurchase: boolean\n}\n\nconst SemigroupCustomer: Semigroup\u003cCustomer\u003e = struct({\n  // keep the longer name\n  name: max(pipe(N.Ord, contramap(S.size))),\n  // accumulate things\n  favouriteThings: RA.getSemigroup\u003cstring\u003e(),\n  // keep the least recent date\n  registeredAt: min(N.Ord),\n  // keep the most recent date\n  lastUpdatedAt: max(N.Ord),\n  // boolean semigroup under disjunction\n  hasMadePurchase: B.SemigroupAny\n})\n\nconsole.log(\n  SemigroupCustomer.concat(\n    {\n      name: 'Giulio',\n      favouriteThings: ['math', 'climbing'],\n      registeredAt: new Date(2018, 1, 20).getTime(),\n      lastUpdatedAt: new Date(2018, 2, 18).getTime(),\n      hasMadePurchase: false\n    },\n    {\n      name: 'Giulio Canti',\n      favouriteThings: ['functional programming'],\n      registeredAt: new Date(2018, 1, 22).getTime(),\n      lastUpdatedAt: new Date(2018, 2, 9).getTime(),\n      hasMadePurchase: true\n    }\n  )\n)\n/*\n{ name: 'Giulio Canti',\n  favouriteThings: [ 'math', 'climbing', 'functional programming' ],\n  registeredAt: 1519081200000, // new Date(2018, 1, 20).getTime()\n  lastUpdatedAt: 1521327600000, // new Date(2018, 2, 18).getTime()\n  hasMadePurchase: true\n}\n*/\n```\n\n**Quiz**. Given a type `A` is it possible to define a `Semigroup\u003cOrd\u003cA\u003e\u003e` instance? What could it possibly represent?\n\n**Demo**\n\n# Modeling composition through Monoids\n\nLet's recap what we have seen till now.\n\nWe have seen how an **algebra** is a combination of:\n\n- some type `A`\n- some operations involving the type `A`\n- some laws and properties for that combination.\n\nThe first algebra we have seen has been the magma, an algebra defined on some type A equipped with one operation called `concat`. There were no laws involved in `Magma\u003cA\u003e` the only requirement we had was that the `concat` operation had to be _closed_ on `A` meaning that the result:\n\n```ts\nconcat(first: A, second: A) =\u003e A\n```\n\nhas still to be an element of the `A` type.\n\nLater on we have seen how adding one simple requirement, _associativity_, allowed some `Magma\u003cA\u003e` to be further refined as a `Semigroup\u003cA\u003e`, and how associativity captures the possibility of computations to be parallelized.\n\nNow we're going to add another condition on Semigroup.\n\nGiven a `Semigroup` defined on some set `A` with some `concat` operation, if there is some element in `A` – we'll call this element _empty_ – such as for every element `a` in `A` the two following equations hold true:\n\n- **Right identity**: `concat(a, empty) = a`\n- **Left identity**: `concat(empty, a) = a`\n\nthen the `Semigroup` is also a `Monoid`.\n\n**Note**: We'll call the `empty` element **unit** for the rest of this section. There's other synonyms in literature, some of the most common ones are _neutral element_ and _identity element_.\n\nWe have seen how in TypeScript `Magma`s and `Semigroup`s, can be modeled with `interface`s, so it should not come as a surprise that the very same can be done for `Monoid`s.\n\n```ts\nimport { Semigroup } from 'fp-ts/Semigroup'\n\ninterface Monoid\u003cA\u003e extends Semigroup\u003cA\u003e {\n  readonly empty: A\n}\n```\n\nMany of the semigroups we have seen in the previous sections can be extended to become `Monoid`s. All we need to find is some element of type `A` for which the Right and Left identities hold true.\n\n```ts\nimport { Monoid } from 'fp-ts/Monoid'\n\n/** number `Monoid` under addition */\nconst MonoidSum: Monoid\u003cnumber\u003e = {\n  concat: (first, second) =\u003e first + second,\n  empty: 0\n}\n\n/** number `Monoid` under multiplication */\nconst MonoidProduct: Monoid\u003cnumber\u003e = {\n  concat: (first, second) =\u003e first * second,\n  empty: 1\n}\n\nconst MonoidString: Monoid\u003cstring\u003e = {\n  concat: (first, second) =\u003e first + second,\n  empty: ''\n}\n\n/** boolean monoid under conjunction */\nconst MonoidAll: Monoid\u003cboolean\u003e = {\n  concat: (first, second) =\u003e first \u0026\u0026 second,\n  empty: true\n}\n\n/** boolean monoid under disjunction */\nconst MonoidAny: Monoid\u003cboolean\u003e = {\n  concat: (first, second) =\u003e first || second,\n  empty: false\n}\n```\n\n**Quiz**. In the semigroup section we have seen how the type `ReadonlyArray\u003cstring\u003e` admits a `Semigroup` instance:\n\n```ts\nimport { Semigroup } from 'fp-ts/Semigroup'\n\nconst Semigroup: Semigroup\u003cReadonlyArray\u003cstring\u003e\u003e = {\n  concat: (first, second) =\u003e first.concat(second)\n}\n```\n\nCan you find the `unit` for this semigroup? If so, can we generalize the result not just for `ReadonlyArray\u003cstring\u003e` but `ReadonlyArray\u003cA\u003e` as well?\n\n**Quiz** (more complex). Prove that given a monoid, there can only be one unit.\n\nThe consequence of the previous proof is that there can be only one unit per monoid, once we find one we can stop searching.\n\nWe have seen how each semigroup was a magma, but not every magma was a semigroup. In the same way, each monoid is a semigroup, but not every semigroup is a monoid.\n\n\u003ccenter\u003e\n\u003cimg src=\"images/monoid.png\" width=\"300\" alt=\"Magma vs Semigroup vs Monoid\" /\u003e\n\u003c/center\u003e\n\n**Example**\n\nLet's consider the following example:\n\n```ts\nimport { pipe } from 'fp-ts/function'\nimport { intercalate } from 'fp-ts/Semigroup'\nimport * as S from 'fp-ts/string'\n\nconst SemigroupIntercalate = pipe(S.Semigroup, intercalate('|'))\n\nconsole.log(S.Semigroup.concat('a', 'b')) // =\u003e 'ab'\nconsole.log(SemigroupIntercalate.concat('a', 'b')) // =\u003e 'a|b'\nconsole.log(SemigroupIntercalate.concat('a', '')) // =\u003e 'a|'\n```\n\nNote how for this Semigroup there's no such `empty` value of type `string` such as `concat(a, empty) = a`.\n\nAnd now one final, slightly more \"exotic\" example, involving functions:\n\n**Example**\n\nAn **endomorphism** is a function whose input and output type is the same:\n\n```ts\ntype Endomorphism\u003cA\u003e = (a: A) =\u003e A\n```\n\nGiven a type `A`, all endomorphisms defined on `A` are a monoid, such as:\n\n- the `concat` operation is the usual function composition\n- the unit, our `empty` value is the identity function\n\n```ts\nimport { Endomorphism, flow, identity } from 'fp-ts/function'\nimport { Monoid } from 'fp-ts/Monoid'\n\nexport const getEndomorphismMonoid = \u003cA\u003e(): Monoid\u003cEndomorphism\u003cA\u003e\u003e =\u003e ({\n  concat: flow,\n  empty: identity\n})\n```\n\n**Note**: The `identity` function has one, and only one possible implementation:\n\n```ts\nconst identity = (a: A) =\u003e a\n```\n\nWhatever value we pass in input, it gives us the same value in output.\n\n\u003c!--\nTODO:\nWe can start having a small taste of the importance of the `identity` function. While apparently useless per se, this function is vital to define a monoid for functions, in this case, endomorphisms. In fact, _doing nothing_, being _empty_ or _neutral_ is a tremendously valuable property to have when it comes to composition and we can think of the `identity` function as the number `0` of functions.\n--\u003e\n\n## The `concatAll` function\n\nOne great property of monoids, compared to semigrops, is that the concatenation of multiple elements becomes even easier: it is not necessary anymore to provide an initial value.\n\n```ts\nimport { concatAll } from 'fp-ts/Monoid'\nimport * as S from 'fp-ts/string'\nimport * as N from 'fp-ts/number'\nimport * as B from 'fp-ts/boolean'\n\nconsole.log(concatAll(N.MonoidSum)([1, 2, 3, 4])) // =\u003e 10\nconsole.log(concatAll(N.MonoidProduct)([1, 2, 3, 4])) // =\u003e 24\nconsole.log(concatAll(S.Monoid)(['a', 'b', 'c'])) // =\u003e 'abc'\nconsole.log(concatAll(B.MonoidAll)([true, false, true])) // =\u003e false\nconsole.log(concatAll(B.MonoidAny)([true, false, true])) // =\u003e true\n```\n\n**Quiz**. Why is the initial value not needed anymore?\n\n## Product monoid\n\nAs we have already seen with semigroups, it is possible to define a monoid instance for a `struct` if we are able to define a monoid instance for each of its fields.\n\n**Example**\n\n```ts\nimport { Monoid, struct } from 'fp-ts/Monoid'\nimport * as N from 'fp-ts/number'\n\ntype Point = {\n  readonly x: number\n  readonly y: number\n}\n\nconst Monoid: Monoid\u003cPoint\u003e = struct({\n  x: N.MonoidSum,\n  y: N.MonoidSum\n})\n```\n\n**Note**. There is a combinator similar to `struct` that works with tuples: `tuple`.\n\n```ts\nimport { Monoid, tuple } from 'fp-ts/Monoid'\nimport * as N from 'fp-ts/number'\n\ntype Point = readonly [number, number]\n\nconst Monoid: Monoid\u003cPoint\u003e = tuple(N.MonoidSum, N.MonoidSum)\n```\n\n**Quiz**. Is it possible to define a \"free monoid\" for a generic type `A`?\n\n**Demo** (implementing a system to draw geoetric shapes on canvas)\n\n[`03_shapes.ts`](src/03_shapes.ts)\n\n# Pure and partial functions\n\nIn the first chapter we've seen an informal definition of a pure function:\n\n\u003e A pure function is a procedure that given the same input always returns the same output and does not have any observable side effect.\n\nSuch an informal statement could leave space for some doubts, such as:\n\n- what is a \"side effect\"?\n- what does it means \"observable\"?\n- what does it mean \"same\"?\n\nLet's see a formal definition of the concept of a function.\n\n**Note**. If `X` and `Y` are sets, then with `X × Y` we indicate their _cartesian product_, meaning the set\n\n```\nX × Y = { (x, y) | x ∈ X, y ∈ Y }\n```\n\nThe following [definition](https://en.wikipedia.org/wiki/History_of_the_function_concept) was given a century ago:\n\n**Definition**. A \\_function: `f: X ⟶ Y` is a subset of `X × Y` such as\nfor every `x ∈ X` there's exactly one `y ∈ Y` such that `(x, y) ∈ f`.\n\nThe set `X` is called the _domain_ of `f`, `Y` is it's _codomain_.\n\n**Example**\n\nThe function `double: Nat ⟶ Nat` is the subset of the cartesian product `Nat × Nat` given by `{ (1, 2), (2, 4), (3, 6), ...}`.\n\nIn TypeScript we could define `f` as\n\n```ts\nconst f: Record\u003cnumber, number\u003e = {\n  1: 2,\n  2: 4,\n  3: 6\n  ...\n}\n```\n\n\u003c!--\nTODO:\nPlease note that the set `f` has to be described _statically_ when defining the function (meaning that the elements of that set cannot change with time for no reason).\nIn this way we can exclude any form of side effect and the return value is always the same.\n--\u003e\n\nThe one in the example is called an _extensional_ definition of a function, meaning we enumerate one by one each of the elements of its domain and for each one of them we point the corresponding codomain element.\n\nNaturally, when such a set is infinite this proves to be problematic. We can't list the entire domain and codomain of all functions.\n\nWe can get around this issue by introducing the one that is called _intensional_ definition, meaning that we express a condition that has to hold for every couple `(x, y) ∈ f` meaning `y = x * 2`.\n\nThis the familiar form in which we write the `double` function and its definition in TypeScript:\n\n```ts\nconst double = (x: number): number =\u003e x * 2\n```\n\nThe definition of a function as a subset of a cartesian product shows how in mathematics every function is pure: there is no action, no state mutation or elements being modified.\nIn functional programming the implementation of functions has to follow as much as possible this ideal model.\n\n**Quiz**. Which of the following procedures are pure functions?\n\n```ts\nconst coefficient1 = 2\nexport const f1 = (n: number) =\u003e n * coefficient1\n\n// ------------------------------------------------------\n\nlet coefficient2 = 2\nexport const f2 = (n: number) =\u003e n * coefficient2++\n\n// ------------------------------------------------------\n\nlet coefficient3 = 2\nexport const f3 = (n: number) =\u003e n * coefficient3\n\n// ------------------------------------------------------\n\nexport const f4 = (n: number) =\u003e {\n  const out = n * 2\n  console.log(out)\n  return out\n}\n\n// ------------------------------------------------------\n\ninterface User {\n  readonly id: number\n  readonly name: string\n}\n\nexport declare const f5: (id: number) =\u003e Promise\u003cUser\u003e\n\n// ------------------------------------------------------\n\nimport * as fs from 'fs'\n\nexport const f6 = (path: string): string =\u003e\n  fs.readFileSync(path, { encoding: 'utf8' })\n\n// ------------------------------------------------------\n\nexport const f7 = (\n  path: string,\n  callback: (err: Error | null, data: string) =\u003e void\n): void =\u003e fs.readFile(path, { encoding: 'utf8' }, callback)\n```\n\nThe fact that a function is pure does not imply automatically a ban on local mutability as long as it doesn't leak out of its scope.\n\n![mutable / immutable](images/mutable-immutable.jpg)\n\n**Example** (Implementazion details of the `concatAll` function for monoids)\n\n```ts\nimport { Monoid } from 'fp-ts/Monoid'\n\nconst concatAll = \u003cA\u003e(M: Monoid\u003cA\u003e) =\u003e (as: ReadonlyArray\u003cA\u003e): A =\u003e {\n  let out: A = M.empty // \u003c= local mutability\n  for (const a of as) {\n    out = M.concat(out, a)\n  }\n  return out\n}\n```\n\nThe ultimate goal is to guarantee: **referential transparency**.\n\nThe contract we sign with a user of our APIs is defined by the APIs signature:\n\n```ts\ndeclare const concatAll: \u003cA\u003e(M: Monoid\u003cA\u003e) =\u003e (as: ReadonlyArray\u003cA\u003e) =\u003e A\n```\n\nand by the promise of respecting referential transparency. The technical details of how the function is implemented are not relevant, thus there is maximum freedom implementation-wise.\n\nThus, how do we define a \"side effect\"? Simply by negating referential transparency:\n\n\u003e An expression contains \"side effects\" if it doesn't benefit from referential transparency\n\nNot only functions are a perfect example of one of the two pillars of functional programming, referential transparency, but they're also examples of the second pillar: **composition**.\n\nFunctions compose:\n\n**Definition**. Given `f: Y ⟶ Z` and `g: X ⟶ Y` two functions, then the function `h: X ⟶ Z` defined by:\n\n```\nh(x) = f(g(x))\n```\n\nis called _composition_ of `f` and `g` and is written `h = f ∘ g`\n\nPlease note that in order for `f` and `g` to combine, the domain of `f` has to be included in the codomain of `g`.\n\n**Definition**. A function is said to be _partial_ if it is not defined for each value of its domain.\n\nVice versa, a function defined for all values of its domain is said to be _total_\n\n**Example**\n\n```\nf(x) = 1 / x\n```\n\nThe function `f: number ⟶ number` is not defined for `x = 0`.\n\n**Example**\n\n```ts\n// Get the first element of a `ReadonlyArray`\ndeclare const head: \u003cA\u003e(as: ReadonlyArray\u003cA\u003e) =\u003e A\n```\n\n**Quiz**. Why is the `head` function partial?\n\n**Quiz**. Is `JSON.parse` a total function?\n\n```ts\nparse: (text: string, reviver?: (this: any, key: string, value: any) =\u003e any) =\u003e\n  any\n```\n\n**Quiz**. Is `JSON.stringify` a total function?\n\n```ts\nstringify: (\n  value: any,\n  replacer?: (this: any, key: string, value: any) =\u003e any,\n  space?: string | number\n) =\u003e string\n```\n\nIn functional programming there is a tendency to only define **pure and total functions**. From now on with the term function we'll be specifically referring to \"pure and total function\". So what do we do when we have a partial function in our applications?\n\nA partial function `f: X ⟶ Y` can always be \"brought back\" to a total one by adding a special value, let's call it `None`, to the codomain and by assigning it to the output of `f` for every value of `X` where the function is not defined.\n\n```\nf': X ⟶ Y ∪ None\n```\n\nLet's call it `Option(Y) = Y ∪ None`.\n\n```\nf': X ⟶ Option(Y)\n```\n\nIn functional programming the tendency is to define only pure and and total functions.\n\nIs it possible to define `Option` in TypeScript? In the following chapters we'll see how to do it.\n\n# Algebraic Data Types\n\nA good first step when writing an application or feature is to define it's domain model. TypeScript offers many tools that help accomplishing this task. **Algebraic Data Types** (in short, ADTs) are one of these tools.\n\n\u003c!--\n  What are the other tools?\n--\u003e\n\n## What is an ADT?\n\n\u003e In computer programming, especially functional programming and type theory, an algebraic data type is a kind of composite type, i.e., **a type formed by combining other types**.\n\nTwo common families of algebraic data types are:\n\n- **product types**\n- **sum types**\n\n\u003ccenter\u003e\n\u003cimg src=\"images/adt.png\" width=\"400\" alt=\"ADT\" /\u003e\n\u003c/center\u003e\n\nLet's begin with the more familiar ones: product types.\n\n## Product types\n\nA product type is a collection of types T\u003csub\u003ei\u003c/sub\u003e indexed by a set `I`.\n\nTwo members of this family are `n`-tuples, where `I` is an interval of natural numbers:\n\n```ts\ntype Tuple1 = [string] // I = [0]\ntype Tuple2 = [string, number] // I = [0, 1]\ntype Tuple3 = [string, number, boolean] // I = [0, 1, 2]\n\n// Accessing by index\ntype Fst = Tuple2[0] // string\ntype Snd = Tuple2[1] // number\n```\n\nand structs, where `I` is a set of labels:\n\n```ts\n// I = {\"name\", \"age\"}\ninterface Person {\n  name: string\n  age: number\n}\n\n// Accessing by label\ntype Name = Person['name'] // string\ntype Age = Person['age'] // number\n```\n\nProduct types can be **polimorphic**.\n\n**Example**\n\n```ts\n//                ↓ type parameter\ntype HttpResponse\u003cA\u003e = {\n  readonly code: number\n  readonly body: A\n}\n```\n\n### Why \"product\" types?\n\nIf we label with `C(A)` the number of elements of type `A` (also called in mathematics, **cardinality**), then the following equation hold true:\n\n```ts\nC([A, B]) = C(A) * C(B)\n```\n\n\u003e the cardinality of a product is the product of the cardinalities\n\n**Example**\n\nThe `null` type has cardinality `1` because it has only one member: `null`.\n\n**Quiz**: What is the cardinality of the `boolean` type.\n\n**Example**\n\n```ts\ntype Hour = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12\ntype Period = 'AM' | 'PM'\ntype Clock = [Hour, Period]\n```\n\nType `Hour` has 12 members.\nType `Period` has 2 members.\nThus type `Clock` has `12 * 2 = 24` elements.\n\n**Quiz**: What is the cardinality of the following `Clock` type?\n\n```ts\n// same as before\ntype Hour = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12\n// same as before\ntype Period = 'AM' | 'PM'\n\n// different encoding, no longer a Tuple\ntype Clock = {\n  readonly hour: Hour\n  readonly period: Period\n}\n```\n\n### When can I use a product type?\n\nEach time it's components are **independent**.\n\n```ts\ntype Clock = [Hour, Period]\n```\n\nHere `Hour` and `Period` are independent: the value of `Hour` does not change the value of `Period`. Every legal pair of `[Hour, Period]` makes \"sense\" and is legal.\n\n## Sum types\n\nA sum type is a a data type that can hold a value of different (but limited) types. Only one of these types can be used in a single instance and there is generally a \"tag\" value differentiating those types.\n\nIn TypeScript's official docs they are called [discriminated union](https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html).\n\nIt is important to note that the members of the union have to be **disjoint**, there can't be values that belong to more than one member.\n\n**Example**\n\nThe type:\n\n```ts\ntype StringsOrNumbers = ReadonlyArray\u003cstring\u003e | ReadonlyArray\u003cnumber\u003e\n\ndeclare const sn: StringsOrNumbers\n\nsn.map() // error: This expression is not callable.\n```\n\nis not a disjoint union because the value `[]`, the empty array, belongs to both members.\n\n**Quiz**. Is the following union disjoint?\n\n```ts\ntype Member1 = { readonly a: string }\ntype Member2 = { readonly b: number }\ntype MyUnion = Member1 | Member2\n```\n\nDisjoint unions are recurring in functional programming.\n\nFortunately `TypeScript` has a way to guarantee that a union is disjoint: add a specific field that works as a **tag**.\n\n**Note**: Disjoint unions, sum types and tagged unions are used interchangeably to indicate the same thing.\n\n**Example** (redux actions)\n\nThe `Action` sum type models a portion of the operation that the user can take i a [todo app](https://todomvc.com/).\n\n```ts\ntype Action =\n  | {\n      type: 'ADD_TODO'\n      text: string\n    }\n  | {\n      type: 'UPDATE_TODO'\n      id: number\n      text: string\n      completed: boolean\n    }\n  | {\n      type: 'DELETE_TODO'\n      id: number\n    }\n```\n\nThe `type` tag makes sure every member of the union is disjointed.\n\n**Note**. The name of the field that acts as a tag is chosen by the developer. It doesn't have to be \"type\". In `fp-ts` the convention is to use a `_tag` field.\n\nNow that we've seen few examples we can define more explicitly what algebraic data types are:\n\n\u003e In general, an algebraic data type specifies a sum of one or more alternatives, where each alternative is a product of zero or more fields.\n\nSum types can be **polymorphic** and **recursive**.\n\n**Example** (linked list)\n\n```ts\n//               ↓ type parameter\nexport type List\u003cA\u003e =\n  | { readonly _tag: 'Nil' }\n  | { readonly _tag: 'Cons'; readonly head: A; readonly tail: List\u003cA\u003e }\n//                                                              ↑ recursion\n```\n\n**Quiz** (TypeScript). Which of the following data types is a product or a sum type?\n\n- `ReadonlyArray\u003cA\u003e`\n- `Record\u003cstring, A\u003e`\n- `Record\u003c'k1' | 'k2', A\u003e`\n- `ReadonlyMap\u003cstring, A\u003e`\n- `ReadonlyMap\u003c'k1' | 'k2', A\u003e`\n\n### Constructors\n\nA sum type with `n` elements needs at least `n` **constructors**, one for each member:\n\n**Example** (redux action creators)\n\n```ts\nexport type Action =\n  | {\n      readonly type: 'ADD_TODO'\n      readonly text: string\n    }\n  | {\n      readonly type: 'UPDATE_TODO'\n      readonly id: number\n      readonly text: string\n      readonly completed: boolean\n    }\n  | {\n      readonly type: 'DELETE_TODO'\n      readonly id: number\n    }\n\nexport const add = (text: string): Action =\u003e ({\n  type: 'ADD_TODO',\n  text\n})\n\nexport const update = (\n  id: number,\n  text: string,\n  completed: boolean\n): Action =\u003e ({\n  type: 'UPDATE_TODO',\n  id,\n  text,\n  completed\n})\n\nexport const del = (id: number): Action =\u003e ({\n  type: 'DELETE_TODO',\n  id\n})\n```\n\n**Example** (TypeScript, linked lists)\n\n```ts\nexport type List\u003cA\u003e =\n  | { readonly _tag: 'Nil' }\n  | { readonly _tag: 'Cons'; readonly head: A; readonly tail: List\u003cA\u003e }\n\n// a nullary constructor can be implemented as a constant\nexport const nil: List\u003cnever\u003e = { _tag: 'Nil' }\n\nexport const cons = \u003cA\u003e(head: A, tail: List\u003cA\u003e): List\u003cA\u003e =\u003e ({\n  _tag: 'Cons',\n  head,\n  tail\n})\n\n// equivalent to an array containing [1, 2, 3]\nconst myList = cons(1, cons(2, cons(3, nil)))\n```\n\n### Pattern matching\n\nJavaScript doesn't support [pattern matching](https://github.com/tc39/proposal-pattern-matching) (neither does TypeScript) but we can simulate it with a `match` function.\n\n**Example** (TypeScript, linked lists)\n\n```ts\ninterface Nil {\n  readonly _tag: 'Nil'\n}\n\ninterface Cons\u003cA\u003e {\n  readonly _tag: 'Cons'\n  readonly head: A\n  readonly tail: List\u003cA\u003e\n}\n\nexport type List\u003cA\u003e = Nil | Cons\u003cA\u003e\n\nexport const match = \u003cR, A\u003e(\n  onNil: () =\u003e R,\n  onCons: (head: A, tail: List\u003cA\u003e) =\u003e R\n) =\u003e (fa: List\u003cA\u003e): R =\u003e {\n  switch (fa._tag) {\n    case 'Nil':\n      return onNil()\n    case 'Cons':\n      return onCons(fa.head, fa.tail)\n  }\n}\n\n// returns `true` if the list is empty\nexport const isEmpty = match(\n  () =\u003e true,\n  () =\u003e false\n)\n\n// returns the first element of the list or `undefined`\nexport const head = match(\n  () =\u003e undefined,\n  (head, _tail) =\u003e head\n)\n\n// returns the length of the list, recursively\nexport const length: \u003cA\u003e(fa: List\u003cA\u003e) =\u003e number = match(\n  () =\u003e 0,\n  (_, tail) =\u003e 1 + length(tail)\n)\n```\n\n**Quiz**. Why's the `head` API sub optimal?\n\n-\u003e See the [answer here](src/quiz-answers/pattern-matching.md)\n\n**Note**. TypeScript offers a great feature for sum types: **exhaustive check**. The type checker can _check_, no pun intended, whether all the possible cases are handled by the `switch` defined in the body of the function.\n\n### Why \"sum\" types?\n\nBecause the following identity holds true:\n\n```ts\nC(A | B) = C(A) + C(B)\n```\n\n\u003e The sum of the cardinality is the sum of the cardinalities\n\n**Example** (the `Option` type)\n\n```ts\ninterface None {\n  readonly _tag: 'None'\n}\n\ninterface Some\u003cA\u003e {\n  readonly _tag: 'Some'\n  readonly value: A\n}\n\ntype Option\u003cA\u003e = None | Some\u003cA\u003e\n```\n\nFrom the general formula `C(Option\u003cA\u003e) = 1 + C(A)` we can derive the cardinality of the `Option\u003cboolean\u003e` type: `1 + 2 = 3` members.\n\n### When should I use a sum type?\n\nWhen the components would be **dependent** if implemented with a product type.\n\n**Example** (`React` props)\n\n```ts\nimport * as React from 'react'\n\ninterface Props {\n  readonly editable: boolean\n  readonly onChange?: (text: string) =\u003e void\n}\n\nclass Textbox extends React.Component\u003cProps\u003e {\n  render() {\n    if (this.props.editable) {\n      // error: Cannot invoke an object which is possibly 'undefined' :(\n      this.props.onChange('a')\n    }\n    return \u003cdiv /\u003e\n  }\n}\n```\n\nThe problem here is that `Props` is modeled like a product, but `onChange` **depends** on `editable`.\n\nA sum type fits the use case better:\n\n```ts\nimport * as React from 'react'\n\ntype Props =\n  | {\n      readonly type: 'READONLY'\n    }\n  | {\n      readonly type: 'EDITABLE'\n      readonly onChange: (text: string) =\u003e void\n    }\n\nclass Textbox extends React.Component\u003cProps\u003e {\n  render() {\n    switch (this.props.type) {\n      case 'EDITABLE':\n        this.props.onChange('a') // :)\n    }\n    return \u003cdiv /\u003e\n  }\n}\n```\n\n**Example** (node callbacks)\n\n```ts\ndeclare function readFile(\n  path: string,\n  //         ↓ ---------- ↓ CallbackArgs\n  callback: (err?: Error, data?: string) =\u003e void\n): void\n```\n\nThe result of the `readFile` operation is modeled like a product type (to be more precise, as a tuple) which is later on passed to the `callback` function:\n\n```ts\ntype CallbackArgs = [Error | undefined, string | undefined]\n```\n\nthe callback components though are **dependent**: we either get an `Error` **or** a `string`:\n\n| err         | data        | legal? |\n| ----------- | ----------- | ------ |\n| `Error`     | `undefined` | ✓      |\n| `undefined` | `string`    | ✓      |\n| `Error`     | `string`    | ✘      |\n| `undefined` | `undefined` | ✘      |\n\nThis API is clearly not modeled on the following premise:\n\n\u003e Make impossible state unrepresentable\n\nA sum type would've been a better choice, but which sum type?\nWe'll see how to handle errors in a functional way.\n\n**Quiz**. Recently API's based on callbacks have been largely replaced by their `Promise` equivalents.\n\n```ts\ndeclare function readFile(path: string): Promise\u003cstring\u003e\n```\n\nCan you find some cons of the Promise solution when using static typing like in TypeScript?\n\n## Functional error handling\n\nLet's see how to handle errors in a functional way.\n\nA function that throws exceptions is an example of a partial function.\n\nIn the previous chapters we have seen that every partial function `f` can always be brought back to a total one `f'`.\n\n```\nf': X ⟶ Option(Y)\n```\n\nNow that we know a bit more about sum types in TypeScript we can define the `Option` without much issues.\n\n### The `Option` type\n\nThe type `Option` represents the effect of a computation which may fail (case `None`) or return a type `A` (case `Some\u003cA\u003e`):\n\n```ts\n// represents a failure\ninterface None {\n  readonly _tag: 'None'\n}\n\n// represents a success\ninterface Some\u003cA\u003e {\n  readonly _tag: 'Some'\n  readonly value: A\n}\n\ntype Option\u003cA\u003e = None | Some\u003cA\u003e\n```\n\nConstructors and pattern matching:\n\n```ts\nconst none: Option\u003cnever\u003e = { _tag: 'None' }\n\nconst some = \u003cA\u003e(value: A): Option\u003cA\u003e =\u003e ({ _tag: 'Some', value })\n\nconst match = \u003cR, A\u003e(onNone: () =\u003e R, onSome: (a: A) =\u003e R) =\u003e (\n  fa: Option\u003cA\u003e\n): R =\u003e {\n  switch (fa._tag) {\n    case 'None':\n      return onNone()\n    case 'Some':\n      return onSome(fa.value)\n  }\n}\n```\n\nThe `Option` type can be used to avoid throwing exceptions or representing the optional values, thus we can move from:\n\n```ts\n//                        this is a lie ↓\nconst head = \u003cA\u003e(as: ReadonlyArray\u003cA\u003e): A =\u003e {\n  if (as.length === 0) {\n    throw new Error('Empty array')\n  }\n  return as[0]\n}\n\nlet s: string\ntry {\n  s = String(head([]))\n} catch (e) {\n  s = e.message\n}\n```\n\nwhere the type system is ignorant about the possibility of failure, to:\n\n```ts\nimport { pipe } from 'fp-ts/function'\n\n//                                      ↓ the type system \"knows\" that this computation may fail\nconst head = \u003cA\u003e(as: ReadonlyArray\u003cA\u003e): Option\u003cA\u003e =\u003e\n  as.length === 0 ? none : some(as[0])\n\ndeclare const numbers: ReadonlyArray\u003cnumber\u003e\n\nconst result = pipe(\n  head(numbers),\n  match(\n    () =\u003e 'Empty array',\n    (n) =\u003e String(n)\n  )\n)\n```\n\nwhere **the possibility of an error is encoded in the type system**.\n\nIf we attempt to access the `value` property of an `Option` without checking in which case we are, the type system will warn us about the possibility of getting an error:\n\n```ts\ndeclare const numbers: ReadonlyArray\u003cnumber\u003e\n\nconst result = head(numbers)\nresult.value // type checker error: Property 'value' does not exist on type 'Option\u003cnumber\u003e'\n```\n\nThe only way to access the value contained in an `Option` is to handle also the failure case using the `match` function.\n\n```ts\npipe(result, match(\n  () =\u003e ...handle error...\n  (n) =\u003e ...go on with my business logic...\n))\n```\n\nIs it possible to define instances for the abstractions we've seen in the chapters before? Let's begin with `Eq`.\n\n### An `Eq` instance\n\nSuppose we have two values of type `Option\u003cstring\u003e` and that we want to compare them to check if their equal:\n\n```ts\nimport { pipe } from 'fp-ts/function'\nimport { match, Option } from 'fp-ts/Option'\n\ndeclare const o1: Option\u003cstring\u003e\ndeclare const o2: Option\u003cstring\u003e\n\nconst result: boolean = pipe(\n  o1,\n  match(\n    // onNone o1\n    () =\u003e\n      pipe(\n        o2,\n        match(\n          // onNone o2\n          () =\u003e true,\n          // onSome o2\n          () =\u003e false\n        )\n      ),\n    // onSome o1\n    (s1) =\u003e\n      pipe(\n        o2,\n        match(\n          // onNone o2\n          () =\u003e false,\n          // onSome o2\n          (s2) =\u003e s1 === s2 // \u003c= qui uso l'uguaglianza tra stringhe\n        )\n      )\n  )\n)\n```\n\nWhat if we had two values of type `Option\u003cnumber\u003e`? It would be pretty annoying to write the same code we just wrote above, the only difference afterall would be how we compare the two values contained in the `Option`.\n\nThus we can generalize the necessary code by requiring the user to provide an `Eq` instance for `A` and then derive an `Eq` instance for `Option\u003cA\u003e`.\n\nIn other words we can define a **combinator** `getEq`: given an `Eq\u003cA\u003e` this combinator will return an `Eq\u003cOption\u003cA\u003e\u003e`:\n\n```ts\nimport { Eq } from 'fp-ts/Eq'\nimport { pipe } from 'fp-ts/function'\nimport { match, Option, none, some } from 'fp-ts/Option'\n\nexport const getEq = \u003cA\u003e(E: Eq\u003cA\u003e): Eq\u003cOption\u003cA\u003e\u003e =\u003e ({\n  equals: (first, second) =\u003e\n    pipe(\n      first,\n      match(\n        () =\u003e\n          pipe(\n            second,\n            match(\n              () =\u003e true,\n              () =\u003e false\n            )\n          ),\n        (a1) =\u003e\n          pipe(\n            second,\n            match(\n              () =\u003e false,\n              (a2) =\u003e E.equals(a1, a2) // \u003c= here I use the `A` equality\n            )\n          )\n      )\n    )\n})\n\nimport * as S from 'fp-ts/string'\n\nconst EqOptionString = getEq(S.Eq)\n\nconsole.log(EqOptionString.equals(none, none)) // =\u003e true\nconsole.log(EqOptionString.equals(none, some('b'))) // =\u003e false\nconsole.log(EqOptionString.equals(some('a'), none)) // =\u003e false\nconsole.log(EqOptionString.equals(some('a'), some('b'))) // =\u003e false\nconsole.log(EqOptionString.equals(some('a'), some('a'))) // =\u003e true\n```\n\nThe best thing about being able to define an `Eq` instance for a type `Option\u003cA\u003e` is being able to leverage all of the combiners we've seen previously for `Eq`.\n\n**Example**:\n\nAn `Eq` instance for the type `Option\u003creadonly [string, number]\u003e`:\n\n```ts\nimport { tuple } from 'fp-ts/Eq'\nimport * as N from 'fp-ts/number'\nimport { getEq, Option, some } from 'fp-ts/Option'\nimport * as S from 'fp-ts/string'\n\ntype MyTuple = readonly [string, number]\n\nconst EqMyTuple = tuple\u003cMyTuple\u003e(S.Eq, N.Eq)\n\nconst EqOptionMyTuple = getEq(EqMyTuple)\n\nconst o1: Option\u003cMyTuple\u003e = some(['a', 1])\nconst o2: Option\u003cMyTuple\u003e = some(['a', 2])\nconst o3: Option\u003cMyTuple\u003e = some(['b', 1])\n\nconsole.log(EqOptionMyTuple.equals(o1, o1)) // =\u003e true\nconsole.log(EqOptionMyTuple.equals(o1, o2)) // =\u003e false\nconsole.log(EqOptionMyTuple.equals(o1, o3)) // =\u003e false\n```\n\nIf we slightly modify the imports in the following snippet we can obtain a similar result for `Ord`:\n\n```ts\nimport * as N from 'fp-ts/number'\nimport { getOrd, Option, some } from 'fp-ts/Option'\nimport { tuple } from 'fp-ts/Ord'\nimport * as S from 'fp-ts/string'\n\ntype MyTuple = readonly [string, number]\n\nconst OrdMyTuple = tuple\u003cMyTuple\u003e(S.Ord, N.Ord)\n\nconst OrdOptionMyTuple = getOrd(OrdMyTuple)\n\nconst o1: Option\u003cMyTuple\u003e = some(['a', 1])\nconst o2: Option\u003cMyTuple\u003e = some(['a', 2])\nconst o3: Option\u003cMyTuple\u003e = some(['b', 1])\n\nconsole.log(OrdOptionMyTuple.compare(o1, o1)) // =\u003e 0\nconsole.log(OrdOptionMyTuple.compare(o1, o2)) // =\u003e -1\nconsole.log(OrdOptionMyTuple.compare(o1, o3)) // =\u003e -1\n```\n\n### `Semigroup` and `Monoid` instances\n\nNow, let's suppose we want to \"merge\" two different `Option\u003cA\u003e`s,: there are four different cases:\n\n| x       | y       | concat(x, y) |\n| ------- | ------- | ------------ |\n| none    | none    | none         |\n| some(a) | none    | none         |\n| none    | some(a) | none         |\n| some(a) | some(b) | ?            |\n\nThere's an issue in the last case, we need a recipe to \"merge\" two different `A`s.\n\nIf only we had such a recipe..Isn't that the job our old good friends `Semigroup`s!?\n\n| x        | y        | concat(x, y)           |\n| -------- | -------- | ---------------------- |\n| some(a1) | some(a2) | some(S.concat(a1, a2)) |\n\nAll we need to do is to require the user to provide a `Semigroup` instance for `A` and then derive a `Semigroup` instance for `Option\u003cA\u003e`.\n\n```ts\n// the implementation is left as an exercise for the reader\ndeclare const getApplySemigroup: \u003cA\u003e(S: Semigroup\u003cA\u003e) =\u003e Semigroup\u003cOption\u003cA\u003e\u003e\n```\n\n**Quiz**. Is it possible to add a neutral element to the previous semigroup to make it a monoid?\n\n```ts\n// the implementation is left as an exercise for the reader\ndeclare const getApplicativeMonoid: \u003cA\u003e(M: Monoid\u003cA\u003e) =\u003e Monoid\u003cOption\u003cA\u003e\u003e\n```\n\nIt is possible to define a monoid instance for `Option\u003cA\u003e` that behaves like that:\n\n| x        | y        | concat(x, y)           |\n| -------- | -------- | ---------------------- |\n| none     | none     | none                   |\n| some(a1) | none     | some(a1)               |\n| none     | some(a2) | some(a2)               |\n| some(a1) | some(a2) | some(S.concat(a1, a2)) |\n\n```ts\n// the implementation is left as an exercise for the reader\ndeclare const getMonoid: \u003cA\u003e(S: Semigroup\u003cA\u003e) =\u003e Monoid\u003cOption\u003cA\u003e\u003e\n```\n\n**Quiz**. What is the `empty` member for the monoid?\n\n-\u003e See the [answer here](src/quiz-answers/option-semigroup-monoid-second.md)\n\n**Example**\n\nUsing `getMonoid` we can derive another two useful monoids:\n\n(Monoid returning the left-most non-`None` value)\n\n| x        | y        | concat(x, y) |\n| -------- | -------- | ------------ |\n| none     | none     | none         |\n| some(a1) | none     | some(a1)     |\n| none     | some(a2) | some(a2)     |\n| some(a1) | some(a2) | some(a1)     |\n\n```ts\nimport { Monoid } from 'fp-ts/Monoid'\nimport { getMonoid, Option } from 'fp-ts/Option'\nimport { first } from 'fp-ts/Semigroup'\n\nexport const getFirstMonoid = \u003cA = never\u003e(): Monoid\u003cOption\u003cA\u003e\u003e =\u003e\n  getMonoid(first())\n```\n\nand its dual:\n\n(Monoid returning the right-most non-`None` value)\n\n| x        | y        | concat(x, y) |\n| -------- | -------- | ------------ |\n| none     | none     | none         |\n| some(a1) | none     | some(a1)     |\n| none     | some(a2) | some(a2)     |\n| some(a1) | some(a2) | some(a2)     |\n\n```ts\nimport { Monoid } from 'fp-ts/Monoid'\nimport { getMonoid, Option } from 'fp-ts/Option'\nimport { last } from 'fp-ts/Semigroup'\n\nexport const getLastMonoid = \u003cA = never\u003e(): Monoid\u003cOption\u003cA\u003e\u003e =\u003e\n  getMonoid(last())\n```\n\n**Example**\n\n`getLastMonoid` can be useful to manage optional values. Let's seen an example where we want to derive user settings for a text editor, in this case VSCode.\n\n```ts\nimport { Monoid, struct } from 'fp-ts/Monoid'\nimport { getMonoid, none, Option, some } from 'fp-ts/Option'\nimport { last } from 'fp-ts/Semigroup'\n\n/** VSCode settings */\ninterface Settings {\n  /** Controls the font family */\n  readonly fontFamily: Option\u003cstring\u003e\n  /** Controls the font size in pixels */\n  readonly fontSize: Option\u003cnumber\u003e\n  /** Limit the width of the minimap to render at most a certain number of columns. */\n  readonly maxColumn: Option\u003cnumber\u003e\n}\n\nconst monoidSettings: Monoid\u003cSettings\u003e = struct({\n  fontFamily: getMonoid(last()),\n  fontSize: getMonoid(last()),\n  maxColumn: getMonoid(last())\n})\n\nconst workspaceSettings: Settings = {\n  fontFamily: some('Courier'),\n  fontSize: none,\n  maxColumn: some(80)\n}\n\nconst userSettings: Settings = {\n  fontFamily: some('Fira Code'),\n  fontSize: some(12),\n  maxColumn: none\n}\n\n/** userSettings overrides workspaceSettings */\nconsole.log(monoidSettings.concat(workspaceSettings, userSettings))\n/*\n{ fontFamily: some(\"Fira Code\"),\n  fontSize: some(12),\n  maxColumn: some(80) }\n*/\n```\n\n**Quiz**. Suppose VSCode cannot manage more than `80` columns per row, how could we modify the definition of `monoidSettings` to take that into account?\n\n### The `Either` type\n\nWe have seen how the `Option` data type can be used to handle partial functions, which often represent computations than can fail or throw exceptions.\n\nThis data type might be limiting in some use cases tho. While in the case of success we get `Some\u003cA\u003e` which contains information of type `A`, the other member, `None` does not carry any data. We know it failed, but we don't know the reason.\n\nIn order to fix this we simply need to another data type to represent failure, we'll call it `Left\u003cE\u003e`. We'll also replace the `Some\u003cA\u003e` type with the `Right\u003cA\u003e`.\n\n```ts\n// represents a failure\ninterface Left\u003cE\u003e {\n  readonly _tag: 'Left'\n  readonly left: E\n}\n\n// represents a success\ninterface Right\u003cA\u003e {\n  readonly _tag: 'Right'\n  readonly right: A\n}\n\ntype Either\u003cE, A\u003e = Left\u003cE\u003e | Right\u003cA\u003e\n```\n\nConstructors and pattern matching:\n\n```ts\nconst left = \u003cE, A\u003e(left: E): Either\u003cE, A\u003e =\u003e ({ _tag: 'Left', left })\n\nconst right = \u003cA, E\u003e(right: A): Either\u003cE, A\u003e =\u003e ({ _tag: 'Right', right })\n\nconst match = \u003cE, R, A\u003e(onLeft: (left: E) =\u003e R, onRight: (right: A) =\u003e R) =\u003e (\n  fa: Either\u003cE, A\u003e\n): R =\u003e {\n  switch (fa._tag) {\n    case 'Left':\n      return onLeft(fa.left)\n    case 'Right':\n      return onRight(fa.right)\n  }\n}\n```\n\nLet's get back to the previous callback example:\n\n```ts\ndeclare function readFile(\n  path: string,\n  callback: (err?: Error, data?: string) =\u003e void\n): void\n\nreadFile('./myfile', (err, data) =\u003e {\n  let message: string\n  if (err !== undefined) {\n    message = `Error: ${err.message}`\n  } else if (data !== undefined) {\n    message = `Data: ${data.trim()}`\n  } else {\n    // should never happen\n    message = 'The impossible happened'\n  }\n  console.log(message)\n})\n```\n\nwe can change it's signature to:\n\n```ts\ndeclare function readFile(\n  path: string,\n  callback: (result: Either\u003cError, string\u003e) =\u003e void\n): void\n```\n\nand consume the API in such way:\n\n```ts\nreadFile('./myfile', (e) =\u003e\n  pipe(\n    e,\n    match(\n      (err) =\u003e `Error: ${err.message}`,\n      (data) =\u003e `Data: ${data.trim()}`\n    ),\n    console.log\n  )\n)\n```\n\n# Category theory\n\nWe have seen how a founding pillar of functional programming is **composition**.\n\n\u003e And how do we solve problems? We decompose bigger problems into smaller problems. If the smaller problems are still too big, we decompose them further, and so on. Finally, we write code that solves all the small problems. And then comes the essence of programming: we compose those pieces of code to create solutions to larger problems. Decomposition wouldn't make sense if we weren't able to put the pieces back together. - Bartosz Milewski\n\nBut what does it means exactly? How can we state whether two things _compose_? And how can we say if two things compose _well_?\n\n\u003e Entities are composable if we can easily and generally combine their behaviours in some way without having to modify the entities being combined. I think of composability as being the key ingredient necessary for achieving reuse, and for achieving a combinatorial expansion of what is succinctly expressible in a programming model. - Paul Chiusano\n\nWe've briefly mentioned how a program written in functional styles tends to resemble a pipeline:\n\n```ts\nconst program = pipe(\n  input,\n  f1, // pure function\n  f2, // pure function\n  f3, // pure function\n  ...\n)\n```\n\nBut how simple it is to code in such a style? Let's try:\n\n```ts\nimport { pipe } from 'fp-ts/function'\nimport * as RA from 'fp-ts/ReadonlyArray'\n\nconst double = (n: number): number =\u003e n * 2\n\n/**\n * Given a ReadonlyArray\u003cnumber\u003e the program doubles the first element and returns it\n */\nconst program = (input: ReadonlyArray\u003cnumber\u003e): number =\u003e\n  pipe(\n    input,\n    RA.head, // compilation error! Type 'Option\u003cnumber\u003e' is not assignable to type 'number'\n    double\n  )\n```\n\nWhy do I get a compilation error? Because `head` and `double` do not compose.\n\n```ts\nhead: (as: ReadonlyArray\u003cnumber\u003e) =\u003e Option\u003cnumber\u003e\ndouble: (n: number) =\u003e number\n```\n\n`head`'s codomain is not included in `double`'s domain.\n\nLooks like our goal to program using pure functions is over..Or is it?\n\nWe need to be able to refer to some **rigorous theory**, one able to answer such fundamental questions.\n\nWe need to refer to a **formal definition** of composability.\n\nLuckily, for the last 70 years ago, a large number of researchers, members of the oldest and largest humanity's open source project (mathematics) occupied itself with developing a theory dedicated to composability: **category theory**, a branch of mathematics founded by Saunders Mac Lane along Samuel Eilenberg (1945).\n\n\u003e Categories capture the essence of composition.\n\nSaunders Mac Lane\n\n\u003ccenter\u003e\n\u003cimg src=\"images/maclane.jpg\" width=\"300\" alt=\"Saunders Mac Lane\" /\u003e\n\n(Saunders Mac Lane)\n\n\u003cimg src=\"images/eilenberg.jpg\" width=\"300\" alt=\"Samuel Eilenberg\" /\u003e\n\n(Samuel Eilenberg)\n\n\u003c/center\u003e\n\nWe'll see in the following chapters how a category can form the basis for:\n\n- a model for a generic **programming language**\n- a model for the concept of **composition**\n\n## Definition\n\nThe definition of a category, even though it isn't really complex, is a bit long, thus I'll split it in two parts:\n\n- the first is merely technical (we need to define its constituents)\n- the second one will be more relevant to what we care for: a notion of composition\n\n### Part I (Constituents)\n\nA category is a pair of `(Objects, Morphisms)` where:\n\n- `Objects` is a collection of **objects**\n- `Morphisms` is a collection of **morphisms** (also called \"arrows\") between objects\n\n**Note**. The term \"object\" has nothing to do with the concept of \"objects\" in programming. Just think about those \"objects\" as black boxes we can't inspect, or simple placeholders useful to define the various morphisms.\n\nEvery morphism `f` owns a source object `A` and a target object `B`.\n\nIn every morphism, both `A` and `B` are members of `Objects`. We write `f: A ⟼ B` and we say that \"f is a morphism from A to B\".\n\n\u003cimg src=\"images/morphism.png\" width=\"300\" alt=\"A morphism\" /\u003e\n\n**Note**. For simplicity, from now on, I'll use labels only for objects, skipping the circles.\n\n### Part II (Composition)\n\nThere is an operation, `∘`, called \"composition\", such as the following properties hold true:\n\n- (**composition of morphisms**) every time we have two morphisms `f: A ⟼ B` and `g: B ⟼ C` in `Morphisms` then there has to be a third morphism `g ∘ f: A ⟼ C` in `Morphisms` which is the _composition_ of `f` and `g`\n\n\u003cimg src=\"images/composition.png\" width=\"300\" alt=\"composition\" /\u003e\n\n- (**associativity**) if `f: A ⟼ B`, `g: B ⟼ C` and `h: C ⟼ D` then `h ∘ (g ∘ f) = (h ∘ g) ∘ f`\n\n\u003cimg src=\"images/associativity.png\" width=\"500\" alt=\"associativity\" /\u003e\n\n- (**identity**) for every object `X`, there is a morphism `identity: X ⟼ X` called _identity morphism_ of `X`, such as for every morphism `f: A ⟼ X` and `g: X ⟼ B`, the following equation holds true `identity ∘ f = f` and `g ∘ identity = g`.\n\n\u003cimg src=\"images/identity.png\" width=\"300\" alt=\"identity\" /\u003e\n\n**Example**\n\n\u003cimg src=\"images/category.png\" width=\"300\" alt=\"a simple category\" /\u003e\n\nThis category is very simple, there are three objects and six morphisms (1\u003csub\u003eA\u003c/sub\u003e, 1\u003csub\u003eB\u003c/sub\u003e, 1\u003csub\u003eC\u003c/sub\u003e are the identity morphisms for `A`, `B`, `C`).\n\n## Modeling programming languages with categories\n\nA category can be seen as a simplified model for a **typed programming language**, where:\n\n- objects are **types**\n- morphisms are **functions**\n- `∘` is the usual **function composition**\n\nThe following diagram:\n\n\u003cimg src=\"images/category.png\" width=\"300\" alt=\"a simple programming language\" /\u003e\n\ncan be seen as an imaginary (and simple) programming language with just three types and six functions\n\nExample given:\n\n- `A = string`\n- `B = number`\n- `C = boolean`\n- `f = string =\u003e number`\n- `g = number =\u003e boolean`\n- `g ∘ f = string =\u003e boolean`\n\nThe implementation could be something like:\n\n```ts\nconst idA = (s: string): string =\u003e s\n\nconst idB = (n: number): number =\u003e n\n\nconst idC = (b: boolean): boolean =\u003e b\n\nconst f = (s: string): number =\u003e s.length\n\nconst g = (n: number): boolean =\u003e n \u003e 2\n\n// gf = g ∘ f\nconst gf = (s: string): boolean =\u003e g(f(s))\n```\n\n## A category for TypeScript\n\nWe can define a category, let's call it _TS_, as a simplified model of the TypeScript language, where:\n\n- **objects** are all the possible TypeScript types: `string`, `number`, `ReadonlyArray\u003cstring\u003e`, etc...\n- **morphisms** are all TypeScript functions: `(a: A) =\u003e B`, `(b: B) =\u003e C`, ... where `A`, `B`, `C`, ... are TypeScript types\n- the **identity morphisms** are all encoded in a single polymorphic function `const identity = \u003cA\u003e(a: A): A =\u003e a`\n- **morphism's composition** is the usual function composition (which we know to be associative)\n\nAs a model of TypeScript, the _TS_ category may seem a bit limited: no loops, no `if`s, there's _almost_ nothing... that being said that simplified model is rich enough to help us reach our goal: to reason about a well-defined notion of composition.\n\n## Composition's core problem\n\nIn the _TS_ category we can compose two generic functions `f: (a: A) =\u003e B` and `g: (c: C) =\u003e D` as long as `C = B`\n\n```ts\nfunction flow\u003cA, B, C\u003e(f: (a: A) =\u003e B, g: (b: B) =\u003e C): (a: A) =\u003e C {\n  return (a) =\u003e g(f(a))\n}\n\nfunction pipe\u003cA, B, C\u003e(a: A, f: (a: A) =\u003e B, g: (b: B) =\u003e C): C {\n  return flow(f, g)(a)\n}\n```\n\nBut what happens if `B != C`? How can we compose two such functions? Should we give up?\n\nIn the next section we'll see under which conditions such a composition is possible.\n\n**Spoiler**\n\n- to compose `f: (a: A) =\u003e B` with `g: (b: B) =\u003e C` we use our usual function composition\n- to compose `f: (a: A) =\u003e F\u003cB\u003e` with `g: (b: B) =\u003e C` we need a **functor** instance for `F`\n- to compose `f: (a: A) =\u003e F\u003cB\u003e` with `g: (b: B, c: C) =\u003e D` we need an **applicative functor** instance for `F`\n- to compose `f: (a: A) =\u003e F\u003cB\u003e` with `g: (b: B) =\u003e F\u003cC\u003e` we need a **monad** instance for `F`\n\n\u003cimg src=\"images/spoiler.png\" width=\"900\" alt=\"The four composition recipes\" /\u003e\n\nThe problem we started with at the beginning of this chapter corresponds to the second situation, where `F` is the `Option` type:\n\n```ts\n// A = ReadonlyArray\u003cnumber\u003e, B = number, F = Option\nhead: (as: ReadonlyArray\u003cnumber\u003e) =\u003e Option\u003cnumber\u003e\ndouble: (n: number) =\u003e number\n```\n\nTo solve it, the next chapter will talk about functors.\n\n# Functors\n\nIn the last section we've spoken about the _TS_ category (the TypeScript category) and about function composition's core problem:\n\n\u003e How can we compose two generic functions `f: (a: A) =\u003e B` and `g: (c: C) =\u003e D`?\n\nWhy is finding solutions to this problem so important?\n\nBecause, if it is true that categories can be used to model programming languages, morphisms (functions in the _TS_ category) can be used to model **programs**.\n\nThus, solving this abstract problem means finding a concrete way of **composing programs in a generic way**. And _that_ is really interesting for us developers, isn't it?\n\n## Functions as programs\n\nIf we want to model programs with functions we need to tackle an issue immediately:\n\n\u003e How is it possible to model a program that produces side effects with a pure function?\n\nThe answer is to model side effects through **effects**, meaning types that **represent** side effects.\n\nLet's see two possible techniques to do so in JavaScript:\n\n- define a DSL (domain specific language) for effects\n- use a _thunk_\n\nThe first technique, using a DSL, means modifying a program like:\n\n```ts\nfunction log(message: string): void {\n  console.log(message) // side effect\n}\n```\n\nchanging its codomain to make the function return a **description** of the side effect:\n\n```ts\ntype DSL = ... // sum type of every possible effect handled by the system\n\nfunction log(message: string): DSL {\n  return {\n    type: \"log\",\n    message\n  }\n}\n```\n\n**Quiz**. Is the freshly defined `log` function really pure? Actually `log('foo') !== log('foo')`!\n\nThis technique requires a way to combine effects and the definition of an interpreter able to execute the side effects when launching the final program.\n\nThe second technique, way simpler in TypeScript, is to enclose the computation in a _thunk_:\n\n```ts\n// a thunk representing a synchronous side effect\ntype IO\u003cA\u003e = () =\u003e A\n\nconst log = (message: string): IO\u003cvoid\u003e =\u003e {\n  return () =\u003e console.log(message) // returns a thunk\n}\n```\n\nThe `log` program, once executed, won't cause immediately a side effect, but returns **a value representing the computation** (also known as _action_).\n\n```ts\nimport { IO } from 'fp-ts/IO'\n\nexport const log = (message: string): IO\u003cvoid\u003e =\u003e {\n  return () =\u003e console.log(message) // returns a thunk\n}\n\nexport const main = log('hello!')\n// there's nothing in the output at this point\n// because `main` is only an inert value\n// representing the computation\n\nmain()\n// only when launching the program I will see the result\n```\n\nIn functional programming there's a tendency to shove side effects (under the form of effects) to the border of the system (the `main` function) where they are executed by an interpreter obtaining the following schema:\n\n\u003e system = pure core + imperative shell\n\nIn _purely functional_ languages (like Haskell, PureScript or Elm) this division is strict and clear and imposed by the very languages.\n\nEven with this thunk technique (the same technique used in `fp-ts`) we need a way to combine effects, which brings us back to our goal of composing programs in a generic way, let's see how.\n\nWe first need a bit of (informal) terminology: we'll call **pure program** a function with the following signature:\n\n```ts\n(a: A) =\u003e B\n```\n\nSuch a signature models a program that takes an input of type `A` and returns a result of type `B` without any effect.\n\n**Example**\n\nThe `len` program:\n\n```ts\nconst len = (s: string): number =\u003e s.length\n```\n\nWe'll call an **effectful program** a function with the following signature:\n\n```ts\n(a: A) =\u003e F\u003cB\u003e\n```\n\nSuch a signature models a program that takes an input of type `A` and returns a result of type `B` together with an **effect** `F`, where `F` is some sort of type constructor.\n\nLet's recall that a [type constructor](https://en.wikipedia.org/wiki/Type_constructor) is an `n`-ary type operator that takes as argument one or more types and returns another type. We have seen examples of such constructors as `Option`, `ReadonlyArray`, `Either`.\n\n**Example**\n\nThe `head` program:\n\n```ts\nimport { Option, some, none } from 'fp-ts/Option'\n\nconst head = \u003cA\u003e(as: ReadonlyArray\u003cA\u003e): Option\u003cA\u003e =\u003e\n  as.length === 0 ? none : some(as[0])\n```\n\nis a program with an `Option` effect.\n\nWhen we talk about effects we are interested in `n`-ary type constructors where `n \u003e= 1`, example given:\n\n| Type constructor   | Effect (interpretation)                        |\n| ------------------ | ---------------------------------------------- |\n| `ReadonlyArray\u003cA\u003e` | a non deterministic computation                |\n| `Option\u003cA\u003e`        | a computation that may fail                    |\n| `Either\u003cE, A\u003e`     | a computation that may fail                    |\n| `IO\u003cA\u003e`            | a synchronous computation that **never fails** |\n| `Task\u003cA\u003e`          | an asynchronous computation **never fails**    |\n| `Reader\u003cR, A\u003e`     | reading from an environment                    |\n\nwhere\n\n```ts\n// a thunk returning a `Promise`\ntype Task\u003cA\u003e = () =\u003e Promise\u003cA\u003e\n```\n\n```ts\n// `R` represents an \"environment\" needed for the computation\n// (we can \"read\" from it) and `A` is the result\ntype Reader\u003cR, A\u003e = (r: R) =\u003e A\n```\n\nLet's get back to our core problem:\n\n\u003e How do we compose two generic functions `f: (a: A) =\u003e B` e `g: (c: C) =\u003e D`?\n\nWith our current set of rules this general problem is not solvable. We need to add some _boundaries_ to `B` and `C`.\n\nWe already know that if `B = C` then the solution is the usual function composition.\n\n```ts\nfunction flow\u003cA, B, C\u003e(f: (a: A) =\u003e B, g: (b: B) =\u003e C): (a: A) =\u003e C {\n  return (a) =\u003e g(f(a))\n}\n```\n\nBut what about other cases?\n\n## A boundary that leads to functors\n\nLet's consider the following boundary: `B = F\u003cC\u003e` for some type constructor `F`, we have the following situation:\n\n- `f: (a: A) =\u003e F\u003cB\u003e` is an effectful program\n- `g: (b: B) =\u003e C` is a pure program\n\nIn order to compose `f` with `g` we need to find a procedure that allows us to derive a function `g` from a function `(b: B) =\u003e C` to a function `(fb: F\u003cB\u003e) =\u003e F\u003cC\u003e` in order to use the usual function composition (this way the codomain of `f` would be the same of the new function's domain).\n\n\u003cimg src=\"images/map.png\" width=\"500\" alt=\"map\" /\u003e\n\nWe have mutated the origi","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenricopolanski%2Ffunctional-programming","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fenricopolanski%2Ffunctional-programming","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenricopolanski%2Ffunctional-programming/lists"}