Skip to content

Commit 3c0109b

Browse files
author
Cuihtlauac ALVARADO
committed
Inception of a document about Seq
1 parent 41572d8 commit 3c0109b

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

data/tutorials/ds_05_seq.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
id: Sequences
3+
title: Sequences
4+
description: >
5+
Learn about one of OCaml's must used, built-in data types
6+
category: "data-structures"
7+
date: 2023-01-12T09:00:00-01:00
8+
---
9+
10+
# Sequences
11+
12+
A sequence looks a lot like a list. However from a pragmatic perspective, one
13+
should imagine it may be infinite. One way to look at a value of type `'a Seq.t`
14+
is to consider it as an icicle, a frozen stream of data. To understand this
15+
analogy, consider how sequences are defined in the standard libary:
16+
```ocaml
17+
type 'a node =
18+
| Nil
19+
| Cons of 'a * 'a t
20+
and 'a t = unit -> 'a node
21+
```
22+
This is the mutually recursive definition of two types; `Seq.node` which is almost
23+
the same as `list`:
24+
```ocaml
25+
type 'a list =
26+
| []
27+
| (::) of 'a * 'a list
28+
```
29+
and `Seq.t` which is merely a type alias for `unit -> 'a Seq.node`. The whole
30+
point of this definition is the type of second argument of `Seq.Cons`, in `list`
31+
it is a list while in `Seq.t` it is function. Empty lists and empty sequence are
32+
defined the same way (`Seq.Nil` and `[]`). Non-empty lists are non-empty
33+
sequences values are both pairs those former member is a piece of data. But non
34+
empty sequence values have a sequence returning function as latter member
35+
instead of a list. That function is the frozen part of the sequence. When a
36+
non-empty sequence is processed, access to data at the tip of the sequence is
37+
immediate, but access to the rest of the sequence is deferred. To access the
38+
tail of non-empty sequence, it has to be microwaved, that is, the tail returning
39+
function must be passed a `unit` value.
40+
41+
Having frozen-by-function tails explains why sequences should be considered
42+
potentially infinite. Unless a `Seq.Nil` has been found in the sequence, one
43+
can't say for sure if some will ever appear. The tail could be a stream of
44+
client requests in a server, readings from an embedded sensor or logs. All have
45+
unforseenable termination and should be considered infinite.
46+
47+
Here is how to build seemingly infinite sequences of integers.
48+
```ocaml
49+
# let rec ints_from n : int Seq.t = fun () -> Seq.Cons (n, ints_from (n + 1));;
50+
val ints_from : int -> int Seq.t = <fun>
51+
# let ints = ints_from 0;;
52+
val ints : ints Seq.t = <fun>
53+
```
54+
The function `ints_from n` looks as if building the infinite sequence $(n; n +
55+
1; n + 2; n + 3;...)$ while the value `ints` looks as if representing the
56+
infinite sequence $(0; 1; 2; 3; ...)$. In reality, since there isn't an infinite
57+
amount of distinct values of type `int`, those sequences are not increasing,
58+
when reaching `max_int` the values will circle down to `min_int`, actually they
59+
are ultimately periodic.
60+
61+
The OCaml standard library contains a module on sequences called `Seq`. It contains an `Seq.iter` function, which has the same behaviour as `List.iter`. Writting this
62+
```ocaml
63+
# Seq.iter print_int ints;;
64+
```
65+
in an OCaml toplevel actually means: “print integers forever” and you have to
66+
type `Crtl-C` to interrupt the execution. Perhaps more interestingly, the
67+
following code is an infinite loop:
68+
```ocaml
69+
# Seq.iter ignore ints;;
70+
```
71+
But the key point is: it doesn't leak memory.

0 commit comments

Comments
 (0)