Skip to content

Commit 3a7125e

Browse files
committed
update
1 parent 1ddf111 commit 3a7125e

44 files changed

Lines changed: 1789 additions & 315 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

_site/0-book/unit-1/section-2/1-first-class-function.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ In typical school math, functions (like `f(x) = x * 2 + 1`) are primarily unders
1212

1313
**The Extension: Functions as Values in Functional Programming**
1414

15-
Functional programming builds upon this foundation by introducing a powerful extension: the idea that _**functions themselves are values**_, just like numbers or strings. They become **"first-class citizens."
15+
Functional programming builds upon this foundation by introducing a powerful extension: the idea that _**functions themselves are values**_, just like numbers or strings. They become **"first-class citizens."**
1616

1717
While this might be a new way of thinking compared to the typical school math perspective, it's a natural evolution within the mathematical thinking embraced by FP.
1818

_site/0-book/unit-1/section-5/0-how-to-drive.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ To get a computer to do any work, we need to give it "instructions." There are s
88

99
Imperative code is like a cooking recipe; it's a style where you instruct the computer step-by-step: "Do this, then do this, then do that..."
1010

11-
- Step-by-Step is Fundamental:
11+
- **Step-by-Step is Fundamental:**
1212

1313
Code is basically executed line by line, in order, from top to bottom as it's physically written. The computer faithfully follows this flow of instructions, telling it what to do next.
1414

15-
- Control Flow:
15+
- **Control Flow:**
1616

1717
Just flowing from top to bottom isn't enough for complex tasks. So, there are mechanisms to control this flow:
1818

@@ -25,11 +25,11 @@ In imperative code, you describe the series of actions you want the computer to
2525

2626
Functional code has a different flavor compared to imperative code. Rather than giving detailed step-by-step instructions on "how to do it," it's a style that focuses on defining "what should be computed from what" using relationships, much like mathematical functions.
2727

28-
- Computation Defined by Expressions:
28+
- **Computation Defined by Expressions:**
2929

3030
The core of functional code is the "expression." The entire computation is constructed from relationships: which expression needs to be evaluated to obtain a certain value, and on which other values or results of other expressions does that expression, in turn, depend.
3131

32-
- Order of Computation is Determined by Dependencies:
32+
- **Order of Computation is Determined by Dependencies:**
3333

3434
The physical order in which code is written doesn't necessarily dictate the direct order of execution. Instead, if the result of computation A is needed for computation B, then computation A naturally needs to happen before computation B. The order of computation is naturally determined by these dependencies.
3535

1.18 KB

:::lang-en # Set Theory and Types: A Deeper Look Building on our introduction to types and sets from Section 1, let's explore how **set theory** provides the foundation for understanding not just types, but also the algebraic structures we've been studying. ## Set Theory and Functions: The Origins Set theory provides more than just a way to group elements - it gives us the concept of **mappings** between sets. In fact, functions in programming are direct implementations of set-theoretical mappings:

```fsharp // A mapping from integers to booleans let isPositive x = x > 0 // Maps �4 �92 {true, false} // A mapping from one set to another let toString x = x.ToString() // Maps any type �92 string ``` ![image](https://raw.githubusercontent.com/ken-okabe/web-images5/main/img_1745577833678.png) *(This diagram illustrates a function f mapping elements from Set X (Domain, corresponding to an input Type X) to Set Y (Codomain, corresponding to an output Type Y).)* This connection between sets and functions is fundamental. The lambda calculus, the theoretical foundation of functional programming, was developed to formalize these mappings. ![image](https://raw.githubusercontent.com/ken-okabe/web-images5/main/img_1745553771606.png) *(This image often depicts a function as a transformation that takes input from one set and produces output in another, consistent with the set-theoretic view of functions.)* ```fsharp // Mathematical �bbx.x becomes: let id = fun x -> x // Mathematical 3bbx.�bby.x + y becomes: let add = fun x -> fun y -> x + y ``` ## Set Theory: Bottom-Up Understanding Set theory builds our understanding from the ground up: 1. **Elements**: The basic building blocks. ```fsharp let x = 42 // A number let s = "hello" // A string let b = true // A boolean ``` *(These are individual members of their respective sets/types.)* 2. **Sets (Types)**: Collections of elements. ```fsharp type Numbers = int // The set of all integers type Strings = string // The set of all possible strings type Booleans = bool // The set {true, false} ``` ![image](https://raw.githubusercontent.com/ken-okabe/web-images5/main/img_1745564518303.png) *(This diagram visually groups elements into their respective sets: int, string, bool.)* 3. **Structured Types (e.g., Lists as Sets of Elements of a Given Type)**: Types can also define structures that group elements. For instance, `List` is the type representing all possible lists of integers. ```fsharp let intList: List = [1; 2; 3] // An element of the type List ``` The concept of "sets of sets" can be seen in how types like `List>` (a list of integer lists) are formed. ![image](https://raw.githubusercontent.com/ken-okabe/web-images5/main/img_1745564670846.png) *(Visualizing a list as a container holding elements, e.g., `[1,2,3]`.)* ![image](https://raw.githubusercontent.com/ken-okabe/web-images5/main/img_1745564700292.png) *(Illustrating a list of lists, e.g., `[[1,2],[3]]`, where each inner list is an element of the outer list.)* This approach mirrors how we naturally understand collections. Consider a library organization: ```fsharp type Book = { title: string; isbn: string } type Shelf = List // A type whose values are lists of Books type Section = List // A type whose values are lists of Shelves type Library = List

:::lang-en

Set Theory and Types: A Deeper Look

The connection between types (in programming) and sets (in mathematics) forms the foundation for understanding algebraic structures in a programming context.

Let's explore how set theory provides the foundation for understanding not just types, but also the algebraic structures we've been studying.

Set Theory and Functions: The Origins

Set theory provides more than just a way to group elements - it gives us the concept of mappings between sets. In fact, functions in programming are direct implementations of set-theoretical mappings:

// A mapping from integers to booleans
let isPositive x = x > 0  
// A mapping from one set to another
let toString x = x.ToString() 

image

(This diagram illustrates a function f mapping elements from Set X (Domain, corresponding to an input Type X) to Set Y (Codomain, corresponding to an output Type Y).)

This connection between sets and functions is fundamental. The lambda calculus, the theoretical foundation of functional programming, was developed to formalize these mappings.

image

(This image often depicts a function as a transformation that takes input from one set and produces output in another, consistent with the set-theoretic view of functions.)

let id = fun x -> x

let add = fun x -> fun y -> x + y

Set Theory: Bottom-Up Understanding

Set theory builds our understanding from the ground up:

  1. Elements: The basic building blocks.

    let x = 42        // A number
    let s = "hello"   // A string
    let b = true      // A boolean

    (These are individual members of their respective sets/types.)

  2. Sets (Types): Collections of elements.

    type Numbers = int       // The set of all integers
    type Strings = string    // The set of all possible strings
    type Booleans = bool     // The set {true, false}

    image

    (This diagram visually groups elements into their respective sets: int, string, bool.)

  3. Structured Types (e.g., Lists as Sets of Elements of a Given Type): Types can also define structures that group elements. For instance, List<int> is the type representing all possible lists of integers.

    let intList: List<int> = [1; 2; 3] // An element of the type List<int>

    The concept of "sets of sets" can be seen in how types like List<List<int>> (a list of integer lists) are formed.

    image

    (Visualizing a list as a container holding elements, e.g., [1,2,3].)

    image

    (Illustrating a list of lists, e.g., [[1,2],[3]], where each inner list is an element of the outer list.)

This approach mirrors how we naturally understand collections. Consider a library organization:

type Book = { title: string; isbn: string }
type Shelf = List<Book>           // A type whose values are lists of Books
type Section = List<Shelf>        // A type whose values are lists of Shelves
type Library = List<Section>      // A type whose values are lists of Sections

image

(This illustrates a hierarchical structure: a library contains sections, sections contain shelves, and shelves contain books.)

The Relative Nature of Sets and Elements

A crucial insight from set theory is that the distinction between "elements" and "sets" is relative. In our library example:

  1. A Book is an element of type Shelf.
  2. A Shelf (which is a set/collection of Books) is an element of type Section.
  3. A Section is an element of type Library.

This relativity is fundamental:

  • Values are instances (elements) of their types (sets).
  • Complex types (like List<Book>) define sets whose elements are themselves collections or structured data. This mirrors how types work in programming.

Types of Types: A Natural Progression

This relative nature leads to a hierarchy of type constructions:

  1. Simple Types (Basic Sets):

    let n: int = 42      // int is a set of integers
    let b: bool = true   // bool is the set {true, false}
  2. Constructed Types (e.g., Lists, Tuples): These types are formed by applying type constructors to other types.

    let numbers: List<int> = [1; 2; 3]
    // List<int> is a type: the set of all lists of integers.
    let pair: int * int = (1, 2)
    // int * int is a type: the set of all pairs of integers.
  3. Type Constructors (like Functions from Types to Types): These are not types themselves, but "recipes" to create types. List<'T> is a type constructor: given a type 'T', it produces the type List<'T>. Option<'T> is another: given 'T', it produces Option<'T> (a type representing an optional value of 'T').

Values as Singleton Sets: Blurring Lines

An interesting perspective is that individual values can be conceptually viewed as types that contain only one element (singleton sets).

// Conceptually:
// The value 1 can be seen as an instance of a type
// "TheNumberOne" which only contains 1.
let one = 1
// A discriminated union defines a type with a small, fixed set of possible constructors/values.
type DiceFace = One | Two | Three | Four | Five | Six
// Defines the set {One, Two, ..., Six}

image

(This diagram illustrates that a value (like 1) can be thought of as a set containing only itself, and a type (like DiceFace) is a set of specific, enumerated values.)

This perspective suggests that the distinction between "a value" and "a type (as a set)" is not always absolute.

The Limitations of Simple Type Systems

Current mainstream type systems, like F#'s, are powerful but have limitations in directly expressing sets defined by arbitrary properties of values:

// We cannot directly define these as distinct static types in F#
// without runtime checks or more advanced type system features:
// type PositiveInt     
// The set of integers n where n > 0
// type ByteRange       
// The set of integers n where 0 <= n <= 255
// type EvenNumber      
// The set of integers n where n % 2 = 0

This is because such "subset types" or "refined types" often require types to depend on runtime values, blurring the compile-time/runtime distinction.

Dependent Types: The Natural Evolution

Dependent types are a more advanced feature in some type systems (not standard F#) that allow types to be dependent on values.

// Hypothetical dependent type syntax (not valid F#)
type PositiveInt = (n: int) where n > 0
type ByteRange = (n: int) where 0 <= n && n <= 255

This evolution follows naturally from set theory:
  1. Simple types (fixed sets like int).
  2. Generic types / Type constructors (functions from sets to sets, like List<T>).
  3. Dependent types (sets defined by predicates on values).

Sets as Container Types

The sets we have been studying in mathematics are typically called container types in functional programming languages.

image

For example, a List is a container type that can hold multiple values:

// List of numbers
[1; 2; 3; 4; 5]

// List of strings
["apple"; "banana"; "cherry"]

// Nested lists (lists containing lists)
[[1; 2]; [3; 4]; [5; 6]]

The type declaration shows how Lists are generic containers:

image

image

The above is merely a conceptual illustration of container types, so please keep that in mind.

Come to think of it, types like Int and String are themselves sets - Int is a set of numbers like 1, 2, 3..., and String is a set of text strings. So even these basic types could be considered container types.

   // Sets are collections:
   type Numbers = int        // The set of all integers
   type Strings = string    // The set of all possible strings
   type Booleans = bool     // The set {true, false}

image

Everything is relative - a container type is nothing more than a "set of something".

Since List type is the most intuitive image of a Set, for convenience, it's good to start by understanding that List type is the representative example of container types.

:::

_site/0-book/unit-2/section-4/1-category-theory.md

Lines changed: 867 additions & 0 deletions
Large diffs are not rendered by default.

_site/0-book/unit-2/section-4/1-container.md

Lines changed: 0 additions & 56 deletions
This file was deleted.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
:::lang-en
2-
# Functors
2+
# Set Theory and Category Theory
33

44
:::

_site/0-book/unit-2/section-4/2-functor.md renamed to _site/0-book/unit-2/section-5/0-functor.md

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,16 @@
44

55
After exploring **Monoids** as our first algebraic structure, we now turn to another fundamental concept in functional programming: the **Functor** .
66

7-
<img width="100%" src="https://raw.githubusercontent.com/ken-okabe/web-images/main/note.svg">
7+
## Functor in Functional Programming
88

9-
The term **"Functor"** originates from **category theory** , a fascinating branch of mathematics that deals with abstract structures and their relationships. While a complete treatment of category theory would be beyond the scope of this introductory book, we will cover it in detail in a companion volume dedicated to the mathematical foundations of functional programming.
9+
<img width="100%" src="https://raw.githubusercontent.com/ken-okabe/web-images/main/note.svg">
1010

11-
Category theory is indeed a rich and profound field that deserves its own focused treatment. However, mixing its full theoretical depth with our practical introduction to functional programming could potentially overwhelm learners regarding both topics. For now, we'll focus on just the aspects of Functors that are directly relevant to everyday functional programming.
11+
The term **"Functor"** originates from **Category theory** , and this title does not imply that the meaning or concept of Functor differs between functional programming and category theory.
1212

13-
Within the scope of functional programming, we've been dealing exclusively with functions and their theoretical foundation in **set theory** . Category theory's notion of categories is highly abstract, but when we restrict ourselves to set theory (working in what mathematicians call the **"category of sets"** ), things become much more concrete and straightforward.
13+
We are simply focusing on Functors within the scope of set theory(**Category of Sets**), which forms the foundation of functional programming, rather than dealing with the full breadth of category theory.
1414

1515
<img width="100%" src="https://raw.githubusercontent.com/ken-okabe/web-images/main/notefooter.svg">
1616

17-
## Functor in Functional Programming
18-
19-
Note that this title does not imply that the meaning or concept of Functor differs between functional programming and category theory. Rather, as mentioned in the opening note, we are simply focusing on Functors within the scope of set theory, which forms the foundation of functional programming, rather than dealing with the full breadth of category theory.
2017

2118
Let's recall our discussion from "Set Theory and Types: A Deeper Look". We saw this fundamental diagram of mapping:
2219

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
:::lang-en
2+
# Functors
23

3-
# Monads
4-
5-
:::
4+
:::
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)