forked from HigherOrderCO/Bend
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlist.bend
187 lines (165 loc) · 4.7 KB
/
list.bend
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
##############################
# Author: Ematth, 2024
##############################
### Singly-Linked List Type Definition: ###
# The List type is builtin, so we don't need to declare it.
# But this is how it's defined in the builtins file.
# type List:
# Nil
# Cons { head, ~tail }
###########################################
# List clear:
# clears all elements from list l. This is equivalent to initializing an empty list.
clear : (List t) -> (List t) = @l []
# List concat:
# combines two lists (l1, l2) from left to right.
concat : (List t) -> (List t) -> (List t) =
@l1 @l2
match l1 {
List/Cons: (List/Cons l1.head (concat l1.tail l2))
List/Nil: l2
}
# List add_front:
# adds an element e to the front of list l.
add_front : (List t) -> t -> (List t) =
@l @e
match l {
List/Cons: (List/Cons e l)
List/Nil: (List/Cons e List/Nil)
}
# List append (add_back):
# adds an element e to the back of list l.
append : (List t) -> t -> (List t) =
@l @e (concat l (List/Cons e List/Nil))
# list sum:
# returns the sum of all items in the list.
sum : (List u24) -> u24 = @l
match l {
List/Cons: (+ l.head (sum l.tail))
List/Nil: 0
}
# List reverse:
# reverses the order of elements in list l.
reverse.aux : (List t) -> (List t) -> (List t) =
@acc @l
match l {
List/Nil: acc
List/Cons: (reverse.aux (List/Cons l.head acc) l.tail)
}
reverse : (List t) -> (List t) =
@l (reverse.aux [] l)
# List length:
# returns the number of elements in list l.
len : (List t) -> u24 =
@l
match l {
List/Nil: 0
List/Cons: (+ 1 (len l.tail))
}
# List count:
# returns the number of instances of some number n in list l.
count.aux : u24 -> (List u24) -> u24 -> u24 =
@acc @l @n
match l {
List/Nil: acc
List/Cons:
let acc = if (== l.head n) { (+ acc 1) } else { acc }
(count.aux acc l.tail n)
}
count = @l @n
(count.aux 0 l n)
# List index:
# returns the value of a specific list index i, or * if the index doesn't exist.
index : (List t) -> u24 -> (Result t None) =
@l @i
match l {
List/Cons:
switch i {
0: (Result/Ok l.head)
_: (index l.tail (i-1))
}
List/Nil: (Result/Err *)
}
# List head:
# returns the first item in the list, or [] if the list is empty.
head : (List t) -> (Result t None) =
@l
match l {
List/Cons: (Result/Ok l.head)
List/Nil : (Result/Err *)
}
# List tail:
# returns the list whithout the first item, or [] if the list is empty.
tail : (List t) -> (List t) =
@l
match l {
List/Cons: l.tail
List/Nil: []
}
# List equals:
# Compares the elements in two lists and returns 1 if they're equal, and 0 otherwise.
# The function cmp compares two values and returns 1 if they're equal, and 0 otherwise.
equals (xs: (List a)) (ys: (List b)) (cmp: a -> b -> u24) : u24
equals (List/Cons x xs) (List/Cons y ys) cmp = if (cmp x y) { (equals xs ys cmp) } else { 0 }
equals (List/Cons x xs) List/Nil cmp = 0
equals List/Nil (List/Cons y ys) cmp = 0
equals List/Nil List/Nil cmp = 1
# List pop_front:
# removes and discards the first item of list l.
# The new list is returned, or [] if the list is empty.
pop_front : (List t) -> (List t) =
@l
match l {
List/Cons: l.tail
List/Nil: []
}
# List pop_back:
# removes and discards the the last item of list l.
pop_back : (List t) -> (List t)
pop_back (List/Nil) = List/Nil
pop_back (List/Cons x List/Nil) = List/Nil
pop_back (List/Cons head tail) = (List/Cons head (pop_back tail))
# List remove:
# removes the first occurrence of element e from list l.
remove : (List u24) -> u24 -> (List u24) =
@l @s
match l {
List/Cons:
if (== l.head s) {
l.tail
} else {
(List/Cons l.head (remove l.tail s))
}
List/Nil: List/Nil
}
# List split:
# splits list l into two lists (l1, l2) at index i.
# the second list takes the element at index i during the split.
split : (List t) -> u24 -> ((List t), (List t)) =
@l @i (split.aux [] l i)
split.aux : (List t) -> (List t) -> u24 -> ((List t), (List t)) =
@acc @l @i
match l {
List/Cons:
switch i {
0: (acc, l)
_: (split.aux (append acc l.head) l.tail i-1)
}
List/Nil: (acc, [])
}
#################################
def main:
return head([5, 4, 3, 2, 1])
# return sum([1, 2, 3])
# return split([1, 2, 3, 4, 5, 6, 7], 3)
# return remove([1, 2, 1, 3], 1)
# return pop_back([1, 2, 3, 4])
# return pop_front([1, 2, 3])
# return index([5, 3, 6, 8, 2], 0)
# return clear([0, 2, 3])
# return count([1, 2, 3, 3, 3, 4, 4, 5, 3, 1000], 4)
# return len([1, 2, 3, 4, 4, 4])
# return reverse([1, 2, 3, 4, 5])
# return append([1, 2], 3)
# return add_front([2, 3], 1)
# return concat([1, 2], [3, 4])