Skip to content

Commit 640a521

Browse files
committed
docs: update
1 parent deb756f commit 640a521

File tree

15 files changed

+521
-372
lines changed

15 files changed

+521
-372
lines changed

docs/03-proofs.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ We begin by establishing the formal definitions of equality, reflexivity, and sy
131131
The equality relation between two elements $a, b$ of a type $A$ is defined as a dependent type $A.Eq(a, b)$, which asserts that $a$ and $b$ are equal. This is expressed using a dependent type $A \to \mathcal{U}$ where $\mathcal{U}$ is the universe of types. Formally, the equality type $A.Eq(a, b)$ is defined as:
132132

133133
$$
134-
A.Eq(a, b) :\equiv \forall P : (A \to \mathcal{U}), P(a) \to P(b)
134+
Eq_A(a, b) :\equiv \forall (P : A \to \mathcal{U}) . P(a) \to P(b)
135135
$$
136136

137137
This means that $A.Eq(a, b)$ holds if, for all propositions $P$ on $A$, whenever $P(a)$ is true, $P(b)$ must also hold. In essence, this defines equality as the ability to substitute $a$ for $b$ in any context described by $P$.
@@ -150,17 +150,15 @@ The property of **reflexivity** asserts that any element $a$ of a type $A$ is eq
150150
For any element $a \in A$, reflexivity is stated as:
151151

152152
$$
153-
A.Eq(a, a) :\equiv \forall P : (A \to \mathcal{U}), P(a) \to P(a)
153+
\text{refl}_A : \forall(a: A) . Eq_A(a, a) :\equiv \lambda (P : A \to \mathcal{U}) . \lambda (p : P(a)) . p
154154
$$
155155

156156
This is trivially true because the proof $pa : P(a)$ already holds. Reflexivity is defined as:
157157

158158
<div class="code-editor">
159159

160160
```
161-
def refl(A: 'Type, a: A): A.Eq(a, a) = {
162-
(P: A -> 'Type, pa: P(a)) => pa
163-
}
161+
def refl(A: 'Type, a: A): A.Eq(a, a) = (P: A -> 'Type, p: P(a)) => p
164162
```
165163
</div>
166164

@@ -173,7 +171,10 @@ The property of **symmetry** states that if $a = b$, then $b = a$. Formally, giv
173171
The symmetry of equality is defined as follows:
174172

175173
$$
176-
A.Eq(b, a) :\equiv \forall P : (A \to \mathcal{U}), P(b) \to P(a)
174+
\begin{align}
175+
\text{symm}_A : & \, \forall(a, b: A) . Eq_A(a, b) \to Eq_A(b, a)
176+
\\ & :\equiv \lambda (e_{ab} : Eq_A(a, b)) . e_{ab}(\lambda (b' : A) . Eq_A(b', a), \text{refl}_A(a))
177+
\end{align}
177178
$$
178179

179180
Given a proof of $A.Eq(a, b)$, we construct a proof of $A.Eq(b, a)$ by applying $A.Eq(a, b)$ to the proposition $P(b') = A.Eq(b', a)$, and using the reflexivity of $a$. This is formally stated as:
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Decorator
22

3+
!!! warning
4+
This feature is not yet implemented or not fully supported in the current version of Saki interpreter/REPL.
5+
36
A **decorator** in **Saki** is a higher-order function that takes another function as its argument and returns a new function with the same type signature. Decorators allow for the dynamic augmentation of functions with additional functionality, enhancing the behavior of the original function without modifying its core logic. In essence, a decorator has the type:
47

58
$$
File renamed without changes.
File renamed without changes.
Lines changed: 63 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# Expressions
2+
3+
<script type="module" src="/javascripts/editor.js"></script>
4+
<link rel="stylesheet" href="/static/styles.css">
5+
16
## If Expression Terms
27

38
The **if-expression** in **Saki** provides a way to perform conditional branching, allowing a program to execute one of two expressions based on a boolean condition. Unlike some languages where control flow statements are separate from expressions, Saki’s **if-expression** integrates into the language's expression system, meaning that an **if-expression** always evaluates to a value.
@@ -23,10 +28,25 @@ $$
2328
\frac{\Gamma \vdash t_1: \mathbb{B} \quad \Gamma \vdash t_2: T \quad \Gamma \vdash t_3: T}{\Gamma \vdash \text{if } t_1 \text{ then } t_2 \text{ else } t_3 : T}
2429
$$
2530

26-
This rule states that:
31+
Where:
32+
2733
- The condition $t_1$ must have type `Bool` (denoted by $\mathbb{B}$).
2834
- The `then` and `else` branches ($t_2$ and $t_3$) must both have the same type $T$ for the if-expression to be well-typed.
2935

36+
<div class="code-editor" id="code-if">
37+
38+
```
39+
eval {
40+
let value = 10
41+
if value % 2 == 0 then "Even" else "Odd"
42+
}
43+
```
44+
</div>
45+
<div class="button-container">
46+
<button class="md-button button-run" onclick="runCodeInEditor('code-if', 'result-if')">Run Code</button>
47+
</div>
48+
<div class="result-editor" id="result-if"></div>
49+
3050

3151
## Match Expression Terms
3252

@@ -56,39 +76,58 @@ $$
5676
\frac{\Gamma \vdash t: T \quad \Gamma \vdash p_i: T \quad \Gamma \vdash e_i: R}{\Gamma \vdash \text{match } t \ \{ \ p_1 \Rightarrow e_1 \mid \dots \mid p_n \Rightarrow e_n \ \} : R}
5777
$$
5878

59-
This means that:
60-
- The term being matched (`t`) must have type `T`.
61-
- Each pattern `p_i` must match against the type `T`.
62-
- The expression `e_i` associated with each pattern must have the same result type `R`.
63-
- The patterns must be exhaustive, meaning that all possible forms of the term are covered by the patterns.
79+
Where:
6480

65-
### Examples
81+
- The term $t$ being matched must have type $T$.
82+
- Each pattern $p_i$ must correspond to a value of type $T$.
83+
- The expression $e_i$ associated with each pattern must return the same type $R$, ensuring uniformity across all branches.
84+
- The patterns must be exhaustive, covering all possible values of the term $t$. Failing to provide exhaustive patterns would result in a type error, as not all possible values would be handled.
6685

67-
#### Pattern Matching on Algebraic Data Types
86+
### Example: Boolean Pattern Matching
6887

69-
Consider the `Option` type:
88+
In the following example, a boolean value is matched against two patterns: `true` and `false`:
7089

71-
```scala
72-
def getValue[A: 'Type](opt: Option[A], default: A): A = match opt {
73-
case Option[A]::Some(x) => x
74-
case Option[A]::None => default
90+
<div class="code-editor" id="code-match-bool">
91+
92+
```
93+
def toInt(b: Bool): ℤ = match b {
94+
case true => 1
95+
case false => 0
7596
}
97+
98+
eval true.toInt // Result: 1
99+
eval false.toInt // Result: 0
76100
```
101+
</div>
102+
<div class="button-container">
103+
<button class="md-button button-run" onclick="runCodeInEditor('code-match-bool', 'result-match-bool')">Run Code</button>
104+
</div>
105+
<div class="result-editor" id="result-match-bool"></div>
77106

78-
- This function takes an `Option[A]` and a default value.
79-
- If the option is `Some(x)`, it returns `x`; if it is `None`, it returns the default value.
107+
Here, the match-expression transforms a boolean value into an integer representation by explicitly handling both possible cases of a `Bool` type.
80108

81-
#### Exhaustive Matching
109+
### Pattern Matching on Inductive Types
82110

83-
Match expressions must cover all possible cases for the type being matched. For example, when matching on `Bool`:
111+
Pattern matching becomes particularly useful when working with inductive types, which may represent optional values, lists, or other recursively defined structures. Consider the following inductive type `Option`:
112+
113+
<div class="code-editor" id="code-match-option">
84114

85-
```scala
86-
def toInt(b: Bool):= match b with {
87-
case true => 1
88-
case false => 0
89-
}
90115
```
116+
type Option[A: 'Type] = inductive {
117+
None
118+
Some(A)
119+
}
91120
92-
- This function converts a `Bool` value to an integer.
93-
- Both possible values (`true` and `false`) are covered, making the pattern match exhaustive.
121+
def getOrDefault[A: 'Type](opt: Option[A], default: A): A = match opt {
122+
case Option[A]::Some(x) => x
123+
case Option[A]::None => default
124+
}
94125
126+
eval Option[Int]::Some(114514).getOrDefault[Int](0) // Result: 114514
127+
eval Option[Int]::None.getOrDefault[Int](0) // Result: 0
128+
```
129+
</div>
130+
<div class="button-container">
131+
<button class="md-button button-run" onclick="runCodeInEditor('code-match-option', 'result-match-option')">Run Code</button>
132+
</div>
133+
<div class="result-editor" id="result-match-option"></div>
File renamed without changes.
File renamed without changes.

docs/Terms/06-adt.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Algebraic Datatype
2+
3+
<script type="module" src="/javascripts/editor.js"></script>
4+
<link rel="stylesheet" href="/static/styles.css">
5+
6+
**Algebraic Datatype (ADT)** is a special kind of inductive types that are essential in functional programming and type theory. They are used to define composite types by combining other types using **sum types** (also known as **variants**) and **product types**. ADTs are particularly useful for modeling data that can take multiple distinct forms, and they are foundational in expressing complex structures such as trees, lists, and option types. In **Saki**, ADTs are defined using the `enum` keyword and can be parameterized by types and type classes, with the ability to incorporate contract universes for constrained types.
7+
8+
## Syntax of Algebraic Datatypes
9+
10+
The syntax for defining ADTs in Saki follows a straightforward pattern:
11+
12+
```
13+
InductiveCons ::= Ident (‘(’ Term (‘,’ Term)* ‘)’)?
14+
InductiveTypeTerm ::= ‘inductive’ ‘{’ InductiveCons (‘,’ InductiveCons)* ‘}’
15+
```
16+
17+
- **EnumCons**: Represents each constructor of the algebraic datatype. A constructor can either be a simple identifier (like `None`) or an identifier with parameters (like `Some(A)`).
18+
- **EnumTypeTerm**: The ADT is introduced using the `inductive` keyword, followed by a list of constructors enclosed in braces `{}`. Multiple constructors can be defined, separated by commas.
19+
20+
Each constructor defines a specific form that a value of the ADT can take, either as a simple tag or as a combination of different types. ADTs in Saki resemble **sum types** in type theory, where each constructor defines a possible variant of the type.
21+
22+
Algebraic Data Types can be understood as **sum types** in type theory, which are defined using **coproducts**. A sum type, like `A + B`, represents a type that can hold either a value of type `A` or a value of type `B`. In the context of ADTs:
23+
- Each constructor of the ADT corresponds to an inclusion map into the coproduct.
24+
- The ADT represents the **disjoint union** of its constructors.
25+
26+
For instance, the type `Option(A)` is defined as:
27+
$$
28+
\text{Option}(A) \cong 1 + A
29+
$$
30+
Where:
31+
32+
- `1` represents the `None` constructor (the unit type), indicating absence.
33+
- `A` represents the `Some` constructor, indicating presence.
34+
35+
Similarly, the tree type `Tree[A]` can be seen as:
36+
$$
37+
\text{Tree}(A) \cong 1 + (\text{Color} \times A \times \text{Tree}(A) \times \text{Tree}(A))
38+
$$
39+
This reflects the two possible forms of the tree:
40+
41+
- A `Leaf` (represented by `1`).
42+
- A `Node`, which holds a `Color`, a value of type `A`, and two subtrees of type `Tree[A]`.
43+
44+
## Examples of ADTs in Saki
45+
46+
### Simple Algebraic Data Type: `Color`
47+
48+
The following is an example of a simple ADT called `Color`, which represents a type with no parameters and has two distinct values: `Red` and `Black`.
49+
50+
<div class="code-editor">
51+
52+
```
53+
type Color = inductive { Red; Black }
54+
```
55+
</div>
56+
57+
In this case, `Color` is a sum type with two possible values, `Red` and `Black`. Each constructor defines a unique value of the `Color` type. This is a basic example of an ADT, where no additional parameters or data are required.
58+
59+
### Parameterized Algebraic Data Type: `Option`
60+
61+
The `Option` type is a more complex example of an ADT. It represents a type that can either contain a value of type `A` or no value at all.
62+
63+
<div class="code-editor">
64+
65+
```
66+
type Option(A: 'Type) = inductive {
67+
None
68+
Some(A)
69+
}
70+
```
71+
</div>
72+
73+
- **`Option(A)`**: A generic ADT parameterized by a type `A`.
74+
- **`None`**: A constructor representing the absence of a value.
75+
- **`Some(A)`**: A constructor representing the presence of a value of type `A`.
76+
77+
78+
### Nested Algebraic Data Type: `List`
79+
80+
The following example illustrates a recursive ADT that defines a list structure. The `List` type is parameterized by a type `A` and has two constructors: `Nil`, representing an empty list, and `Cons`, which constructs a new list by prepending an element of type `A` to an existing list of type `List[A]`.
81+
82+
<div class="code-editor">
83+
84+
```
85+
type List[A: 'Type] = inductive {
86+
Nil
87+
Cons(A, List[A])
88+
}
89+
```
90+
</div>
91+
92+
- **`Nil`**: Represents an empty list.
93+
- **`Cons(A, List[A])`**: Represents a non-empty list, where the first element is of type `A` and the rest is a list of type `List[A]`.
94+
95+
### Tree Structure Using ADTs: `Tree`
96+
97+
The following example defines a binary tree structure, where each node contains a color, a value of type `A`, and two subtrees of the same type `Tree[A]`.
98+
99+
<div class="code-editor">
100+
101+
```
102+
type Tree[A: 'Type] = inductive {
103+
Leaf
104+
Node(Color, A, Tree[A], Tree[A])
105+
}
106+
```
107+
</div>
108+
109+
- **`Leaf`**: Represents a leaf node, which has no data.
110+
- **`Node(Color, A, Tree[A], Tree[A])`**: Represents an internal node that contains a value of type `A`, a `Color`, and two subtrees of type `Tree[A]`.
111+
112+
113+
## ADT/Inductive Constructor Access
114+
115+
In Saki, the constructors of inductive types (including ADTs) can be accessed using the `::` operator. For example:
116+
117+
<div class="code-editor" id="code-adt-constructor-access">
118+
119+
```
120+
type Option(A: 'Type) = inductive {
121+
None
122+
Some(A)
123+
}
124+
125+
eval Option(Int)::None
126+
eval Option(String)::Some
127+
```
128+
</div>
129+
<div class="button-container">
130+
<button class="md-button button-run" onclick="runCodeInEditor('code-adt-constructor-access', 'result-adt-constructor-access')">Run Code</button>
131+
</div>
132+
<div class="result-editor" id="result-adt-constructor-access"></div>

0 commit comments

Comments
 (0)