-
Notifications
You must be signed in to change notification settings - Fork 2
/
List.fm
161 lines (135 loc) · 3.63 KB
/
List.fm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// List.fm
// =======
//
// Linked lists.
import Equal
import Maybe
import Nat
// Definition
// ----------
T List{A}
| nil
| cons(head : A, tail : List(A))
// Operations
// ----------
// Returns the head
head(A; x : A, xs : List(A)) : A
case xs
| nil => x
| cons => xs.head
// Returns the tail
tail(A; xs : List(A)) : List(A)
case xs
| nil => nil(_)
| cons => xs.tail
// Returns the first element and the rest in a pair
take(A; x : A, xs : List(A)) : Pair(A, List(A))
case xs
| nil => pair(__ x, nil(_))
| cons => pair(__ xs.head, xs.tail)
// Gets the element at an index
at(A; n : Nat, xs : List(A)) : Maybe(A)
case xs
with n : Nat
| nil => none(_)
| cons => case n
| zero => some(_ xs.head)
| succ => at(_ n.pred, xs.tail)
// Finds the first occurrence
find(A; fn: A -> Bool, xs: List(A)) : Maybe(A)
case xs
| nil => none(_)
| cons => case fn(xs.head) as got
| true => some(_ xs.head)
| false => find(_ fn, xs.tail)
// Finds the first occurrence (helper)
find_index.aux(A;
fn: A -> Bool,
xs: List(A),
ix: Nat
) : Maybe(Nat)
case xs
| nil => none(_)
| cons => case fn(xs.head) as got
| true => some(_ ix)
| false => find_index.aux(_ fn, xs.tail, succ(ix))
// Finds the first occurrence
find_index(A; fn: A -> Bool, xs: List(A)) : Maybe(Nat)
find_index.aux(A; fn, xs, 0n)
// Filters a list
filter(A; fn: A -> Bool, xs: List(A)) : List(A)
case xs
| nil => nil(_)
| cons => case fn(xs.head) as got
with xs.tail : List(A)
| true => cons(_ xs.head, xs.tail)
| false => cons(_ xs.head, filter(_ fn, xs.tail))
// Returns the same list
sames(A; xs : List(A)) : List(A)
case xs
| nil => nil(_)
| cons => cons(_ xs.head, sames(_ xs.tail))
// Applies a function to every element of a list
map(A; B; fn: A -> B, xs: List(A)) : List(B)
case xs
| nil => []
| cons => cons(_ fn(xs.head), map(__ fn, xs.tail))
// Folds a list, converting it to its Church encoding
fold(A; B; i: B, f: A -> B -> B, xs: List(A)) : B
case xs
| nil => i
| cons => f(xs.head, fold(A; B; i, f, xs.tail))
// Applies a function to every element of a list
ziply(A; B; fs : List(A -> B), xs : List(A)) : List(B)
case fs
| nil => nil(_)
| cons => case xs
| nil => nil(_)
| cons => cons(_
fs.head(xs.head),
ziply(A; B; fs.tail, xs.tail))
// Concatenates two lists
concat(A; xs : List(A), ys : List(A)) : List(A)
case xs
with ys : List(A)
| nil => ys
| cons => cons(_ xs.head, concat(_ xs.tail, ys))
// Helper for reverse
reverse.go(A; xs : List(A), rs : List(A)) : List(A)
case xs
with rs : List(A)
| nil => rs
| cons => reverse.go(_ xs.tail, cons(A; xs.head, rs))
// Reverses a list
reverse(A; list : List(A)) : List(A)
reverse.go(A; list, nil(_))
// Length of a list
length(A; list : List(A)) : Nat
case list
| nil => zero
| cons => succ(length(A; list.tail))
// Internal
generate.go(A; idx: Number, len: Number, gen: Number -> A)
: List(A)
if idx === len then
[]
else
cons(_ gen(idx), generate.go(A; idx + 1, len, gen))
// Generates a list with a length and a generator function
generate(A; len: Number, gen: Number -> A) : List(A)
generate.go(A; 0, len, gen)
// O(1) concatenator
Concat(A : Type) : Type
(x : List(A)) -> List(A)
// Concatenates a O(1) concatenator
concatenate(A; xs : Concat(A), ys : Concat(A)) : Concat(A)
(x) => xs(ys(x))
// Converts a list to a O(1) concatenator
list_to_concat(A; xs : List(A)) : Concat(A)
(x) => case xs
with x : List(A)
| nil => x
| cons => cons(_ xs.head, list_to_concat(_ xs.tail, x))
// Converts a O(1) concatenator to a list
concat_to_list(A; xs : Concat(A)) : List(A)
xs(nil(_))