@effekt-lang/effekt 0.2.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/README.md +6 -18
  2. package/bin/effekt +0 -0
  3. package/bin/effekt.sh +1 -1
  4. package/libraries/chez/common/effekt_primitives.ss +10 -2
  5. package/libraries/chez/common/immutable/cslist.effekt +13 -7
  6. package/libraries/chez/common/mutable/dict.effekt +8 -10
  7. package/libraries/chez/common/text/regex.effekt +7 -9
  8. package/libraries/common/args.effekt +68 -0
  9. package/libraries/common/array.effekt +220 -0
  10. package/libraries/common/bench.effekt +86 -0
  11. package/libraries/common/buffer.effekt +123 -0
  12. package/libraries/common/bytes.effekt +125 -0
  13. package/libraries/{js/immutable → common}/dequeue.effekt +18 -4
  14. package/libraries/common/effekt.effekt +725 -0
  15. package/libraries/common/exception.effekt +121 -0
  16. package/libraries/common/io/console.effekt +62 -0
  17. package/libraries/common/io/error.effekt +474 -0
  18. package/libraries/common/io/filesystem.effekt +274 -0
  19. package/libraries/common/io/network.effekt +81 -0
  20. package/libraries/common/io/time.effekt +12 -0
  21. package/libraries/common/io.effekt +88 -0
  22. package/libraries/{llvm/immutable → common}/list.effekt +101 -74
  23. package/libraries/common/option.effekt +72 -0
  24. package/libraries/common/process.effekt +9 -0
  25. package/libraries/common/queue.effekt +140 -0
  26. package/libraries/common/ref.effekt +60 -0
  27. package/libraries/common/result.effekt +45 -0
  28. package/libraries/{ml/immutable → common}/seq.effekt +30 -19
  29. package/libraries/common/string/tty.effekt +66 -0
  30. package/libraries/common/string.effekt +361 -0
  31. package/libraries/common/test.effekt +160 -0
  32. package/libraries/js/effekt_builtins.js +37 -6
  33. package/libraries/js/mutable/map.effekt +8 -9
  34. package/libraries/js/text/regex.effekt +7 -8
  35. package/libraries/js/unsafe/cont.effekt +2 -2
  36. package/libraries/js/web/dom.effekt +13 -13
  37. package/libraries/llvm/array.c +53 -0
  38. package/libraries/llvm/buffer.c +181 -76
  39. package/libraries/llvm/forward-declare-c.ll +27 -8
  40. package/libraries/llvm/io.c +423 -1
  41. package/libraries/llvm/main.c +6 -1
  42. package/libraries/llvm/ref.c +45 -0
  43. package/libraries/llvm/rts.ll +515 -354
  44. package/libraries/llvm/types.c +32 -0
  45. package/licenses/eclipse public license, version 2.0 - epl-2.0.html +4 -4
  46. package/licenses/mit license - mit-license.html +532 -62
  47. package/licenses/the bsd license - bsd-license.html +535 -60
  48. package/licenses/the mit license - mit.html +532 -62
  49. package/package.json +2 -2
  50. package/libraries/chez/callcc/effekt.effekt +0 -221
  51. package/libraries/chez/common/effekt_matching.ss +0 -100
  52. package/libraries/chez/common/immutable/dequeue.effekt +0 -78
  53. package/libraries/chez/common/immutable/list.effekt +0 -643
  54. package/libraries/chez/common/immutable/option.effekt +0 -39
  55. package/libraries/chez/common/immutable/result.effekt +0 -29
  56. package/libraries/chez/common/io/args.effekt +0 -20
  57. package/libraries/chez/common/mutable/array.effekt +0 -27
  58. package/libraries/chez/common/mutable/heap.effekt +0 -12
  59. package/libraries/chez/common/test.effekt +0 -59
  60. package/libraries/chez/common/text/string.effekt +0 -46
  61. package/libraries/chez/lift/effekt.effekt +0 -217
  62. package/libraries/chez/lift/effekt.ss +0 -118
  63. package/libraries/chez/monadic/effekt.effekt +0 -218
  64. package/libraries/js/effekt.effekt +0 -284
  65. package/libraries/js/effekt_matching.js +0 -79
  66. package/libraries/js/immutable/list.effekt +0 -643
  67. package/libraries/js/immutable/option.effekt +0 -49
  68. package/libraries/js/immutable/result.effekt +0 -29
  69. package/libraries/js/io/args.effekt +0 -9
  70. package/libraries/js/io/async.effekt +0 -28
  71. package/libraries/js/io/async.js +0 -2
  72. package/libraries/js/io/file.effekt +0 -50
  73. package/libraries/js/io/file_include.js +0 -13
  74. package/libraries/js/mutable/array.effekt +0 -98
  75. package/libraries/js/mutable/heap.effekt +0 -32
  76. package/libraries/js/test.effekt +0 -59
  77. package/libraries/js/text/string.effekt +0 -64
  78. package/libraries/llvm/effekt.effekt +0 -243
  79. package/libraries/llvm/immutable/option.effekt +0 -53
  80. package/libraries/llvm/immutable/result.effekt +0 -29
  81. package/libraries/llvm/io/args.effekt +0 -24
  82. package/libraries/llvm/text/string.effekt +0 -179
  83. package/libraries/ml/effekt.effekt +0 -267
  84. package/libraries/ml/effekt.sml +0 -63
  85. package/libraries/ml/immutable/dequeue.effekt +0 -81
  86. package/libraries/ml/immutable/list.effekt +0 -674
  87. package/libraries/ml/immutable/option.effekt +0 -53
  88. package/libraries/ml/immutable/result.effekt +0 -29
  89. package/libraries/ml/internal/option.effekt +0 -18
  90. package/libraries/ml/io/args.effekt +0 -41
  91. package/libraries/ml/mutable/array.effekt +0 -43
  92. package/libraries/ml/random.effekt +0 -85
  93. package/libraries/ml/test.effekt +0 -60
  94. package/libraries/ml/text/regex.effekt +0 -107
  95. package/libraries/ml/text/string.effekt +0 -81
@@ -1,674 +0,0 @@
1
- module immutable/list
2
-
3
- import effekt
4
- import immutable/option
5
-
6
- // Used as a type for `Exception` in functions which expect a nonempty list.
7
- record EmptyList()
8
-
9
- // Used as a type for `Exception` in functions where an index can be out of bounds.
10
- record OutOfBounds()
11
-
12
- // Immutable linked list for finite sequences of elements.
13
- type List[A] {
14
- Nil();
15
- Cons(head: A, tail: List[A])
16
- }
17
-
18
- // Create an empty list.
19
- //
20
- // O(1)
21
- def empty[A](): List[A] = Nil()
22
-
23
- // Create a list with one element.
24
- //
25
- // O(1)
26
- def singleton[A](x: A): List[A] = Cons(x, Nil())
27
-
28
- // Create a list of length `size` where all elements are `default`.
29
- //
30
- // O(size)
31
- def fill[A](size: Int, default: A): List[A] = {
32
- build(size) { i => default }
33
- }
34
-
35
- // Create a list from a function `index` of given `size`.
36
- //
37
- // O(size)
38
- def build[A](size: Int) { index: Int => A }: List[A] = {
39
- var result = empty()
40
- each(0, size) { i =>
41
- result = Cons(index(i), result)
42
- }
43
- result.reverse
44
- }
45
-
46
- // Check if list is empty.
47
- //
48
- // O(1)
49
- def isEmpty[A](l: List[A]): Boolean = l match {
50
- case Nil() => true
51
- case Cons(a, rest) => false
52
- }
53
-
54
- // Check if list is nonempty.
55
- //
56
- // O(1)
57
- def nonEmpty[A](l: List[A]): Boolean = l match {
58
- case Nil() => false
59
- case Cons(a, rest) => true
60
- }
61
-
62
- // Return the first element of a given list.
63
- // Throws a `EmptyList` exception if it's empty.
64
- //
65
- // O(1)
66
- def head[A](l: List[A]): A / Exception[EmptyList] = l match {
67
- case Nil() => do raise(EmptyList(), "Trying to get the head of an empty list")
68
- case Cons(a, rest) => a
69
- }
70
-
71
- // Return all elements of a given list except the first element.
72
- // Throws a `EmptyList` exception if it's empty.
73
- //
74
- // O(1)
75
- def tail[A](l: List[A]): List[A] / Exception[EmptyList] = l match {
76
- case Nil() => do raise(EmptyList(), "Trying to get the head of an empty list")
77
- case Cons(a, rest) => rest
78
- }
79
-
80
- // Return the first element of a given list.
81
- // Returns `None()` if it's empty.
82
- //
83
- // O(1)
84
- def headOption[A](l: List[A]): Option[A] = l match {
85
- case Nil() => None()
86
- case Cons(a, rest) => Some(a)
87
- }
88
-
89
- // Get the value at given index.
90
- //
91
- // O(N)
92
- def get[A](list: List[A], index: Int): A / Exception[OutOfBounds] = {
93
- def go(list: List[A], i: Int): A / Exception[OutOfBounds] = {
94
- list match {
95
- case Nil() => do raise(OutOfBounds(), "Trying to get an element outside the bounds of a list")
96
- case Cons(x, xs) =>
97
- if (i == 0) {
98
- x
99
- } else {
100
- go(xs, i - 1)
101
- }
102
- }
103
- }
104
-
105
- go(list, index)
106
- }
107
-
108
- // Traverse a list, applying the given action on every element.
109
- //
110
- // O(N)
111
- def foreach[A](l: List[A]) { f: A => Unit / Control } : Unit = {
112
- var remainder = l
113
- loop {
114
- if (not(remainder.isEmpty)) {
115
- remainder match {
116
- case Nil() => ()
117
- case Cons(a, as) =>
118
- remainder = as
119
- f(a)
120
- }
121
- } else { do break() }
122
- }
123
- }
124
-
125
- // Traverse a list, applying the given action on every element and its (zero-based) index.
126
- //
127
- // O(N)
128
- def foreachIndex[A](list: List[A]){ f: (Int, A) => Unit / Control }: Unit = {
129
- var remainder = list
130
- var i = -1
131
- loop {
132
- if (not(remainder.isEmpty)) {
133
- remainder match {
134
- case Nil() => ()
135
- case Cons(a, as) =>
136
- remainder = as
137
- i = i + 1
138
- f(i, a)
139
- }
140
- } else { do break() }
141
- }
142
- }
143
-
144
- // Map a function `f` over elements in a given list.
145
- //
146
- // O(N)
147
- def map[A, B](l: List[A]) { f: A => B } : List[B] = {
148
- var acc = Nil[B]()
149
- l.foreach { el => acc = Cons(f(el), acc) }
150
- acc.reverse
151
- }
152
-
153
- // Map a function `f` over elements in a given list,
154
- // keeping only the elements for which the function returned `Some(...)`,
155
- // discarding the elements for which the function returned `None()`.
156
- //
157
- // O(N)
158
- def collect[A, B](l: List[A]) { f : A => Option[B] }: List[B] = {
159
- var acc = Nil[B]()
160
- l.foreach { a =>
161
- val optB = f(a)
162
- optB match {
163
- case None() => ();
164
- case Some(b) => acc = Cons(b, acc);
165
- }
166
- }
167
- acc.reverse
168
- }
169
-
170
- // Map a function `f` over elements in a given list and concatenate the results.
171
- //
172
- // O(N)
173
- def flatMap[A, B](l: List[A]) { f : A => List[B] }: List[B] = {
174
- var acc = Nil[B]()
175
- l.foreach { a =>
176
- val bs = f(a)
177
- acc = acc.append(bs)
178
- }
179
- acc
180
- }
181
-
182
- // Check if predicate is true for all elements of the given list.
183
- //
184
- // O(N)
185
- def all[A](list: List[A]) { predicate: A => Boolean }: Boolean = {
186
- list match {
187
- case Cons(x, xs) => predicate(x) && all(xs) { predicate }
188
- case Nil() => true
189
- }
190
- }
191
-
192
- // Check if predicate is true for at least one element of the given list.
193
- //
194
- // O(N)
195
- def any[A](list: List[A]) { predicate: A => Boolean }: Boolean = {
196
- list match {
197
- case Cons(x, xs) => predicate(x) || any(xs) { predicate }
198
- case Nil() => false
199
- }
200
- }
201
-
202
- // Sum the elements of the list.
203
- //
204
- // O(N)
205
- def sum(list: List[Int]): Int = {
206
- var n = 0;
207
- list.foreach { x => n = n + x };
208
- n
209
- }
210
-
211
- // Calculate the size of the list.
212
- //
213
- // O(N)
214
- def size[A](l: List[A]): Int = {
215
- var n = 0;
216
- l.foreach { _ => n = n + 1 };
217
- n
218
- }
219
-
220
- // Reverse the list.
221
- //
222
- // O(N)
223
- def reverse[A](l: List[A]): List[A] = {
224
- var res = Nil[A]()
225
- l.foreach { el => res = Cons(el, res) }
226
- res
227
- }
228
-
229
- // Reverse a list `l` and append `other` to it.
230
- //
231
- // Example:
232
- // ```
233
- // > [1,2,3].reverseOnto([4,5,6])
234
- // [3,2,1,4,5,6]
235
- // ```
236
- //
237
- // O(|l|)
238
- def reverseOnto[A](l: List[A], other: List[A]): List[A] = l match {
239
- case Nil() => other
240
- case Cons(a, rest) => rest.reverseOnto(Cons(a, other))
241
- }
242
-
243
- // Concatenate list `l` with list `other`:
244
- //
245
- // Example:
246
- // ```
247
- // > [1,2,3].append([4,5,6])
248
- // [1,2,3,4,5,6]
249
- // ```
250
- //
251
- // O(N)
252
- def append[A](l: List[A], other: List[A]): List[A] =
253
- l.reverse.reverseOnto(other)
254
-
255
- // Flatten a list of lists into a single list.
256
- //
257
- // Examples:
258
- // ```
259
- // > [[1, 2, 3], [4, 5], [6]].join()
260
- // [1, 2, 3, 4, 5, 6]
261
- //
262
- // > [[]].join()
263
- // []
264
- // ```
265
- //
266
- // O(N)
267
- def join[A](lists: List[List[A]]): List[A] = {
268
- var acc: List[A] = Nil()
269
- lists.foreach { list =>
270
- acc = acc.append(list)
271
- }
272
- acc
273
- }
274
-
275
- // Flatten a list of lists into a single list,
276
- // putting the `between` list in between each list in the input.
277
- //
278
- // Examples:
279
- // ```
280
- // > [[100], [200, 300], [400]].join([1, 2, 3])
281
- // [100, 1, 2, 3, 200, 300, 1, 2, 3, 400]
282
- //
283
- // > [[]].join([1, 2, 3])
284
- // []
285
- // ```
286
- //
287
- // O(N)
288
- def join[A](lists: List[List[A]], between: List[A]): List[A] = {
289
- lists match {
290
- case Nil() => Nil()
291
- case Cons(firstList, restOfLists) =>
292
- firstList.append(
293
- restOfLists.flatMap { list => between.append(list)}
294
- )
295
- }
296
- }
297
-
298
- // Take the first `n` elements of a given list.
299
- //
300
- // Examples:
301
- // ```
302
- // > [1, 2, 3].take(2)
303
- // [1, 2]
304
- //
305
- // > [1, 2, 3].take(0)
306
- // []
307
- //
308
- // > [1, 2, 3].take(3)
309
- // [1, 2, 3]
310
- //
311
- // > [1, 2, 3].take(5)
312
- // [1, 2, 3]
313
- //
314
- // > [1, 2, 3].take(-1)
315
- // []
316
- // ```
317
- //
318
- // O(n)
319
- def take[A](l: List[A], n: Int): List[A] =
320
- if (n <= 0) {
321
- Nil()
322
- } else l match {
323
- case Nil() => Nil()
324
- case Cons(a, rest) => Cons(a, rest.take(n - 1))
325
- }
326
-
327
- // Drop the first `n` elements of a given list.
328
- //
329
- // Examples:
330
- // ```
331
- // > [1, 2, 3].drop(2)
332
- // [3]
333
- //
334
- // > [1, 2, 3].drop(0)
335
- // [1, 2, 3]
336
- //
337
- // > [1, 2, 3].drop(3)
338
- // []
339
- //
340
- // > [1, 2, 3].drop(5)
341
- // []
342
- //
343
- // > [1, 2, 3].drop(-1)
344
- // [1, 2, 3]
345
- // ```
346
- //
347
- // O(n)
348
- def drop[A](l: List[A], n: Int): List[A] =
349
- if (n <= 0) {
350
- l
351
- } else l match {
352
- case Nil() => Nil()
353
- case Cons(a, rest) => rest.drop(n - 1)
354
- }
355
-
356
- // Return a slice of a given list from the starting index (inclusive)
357
- // to the given end index (exclusive).
358
- //
359
- // Examples:
360
- // ```
361
- // > [1, 2, 3, 4, 5, 6].slice(1, 4)
362
- // [2, 3, 4]
363
- //
364
- // > [1, 2, 3, 4, 5, 6].slice(1, 2)
365
- // [2]
366
- //
367
- // > [1, 2, 3, 4, 5, 6].slice(1, 1)
368
- // []
369
- //
370
- // > [1, 2, 3, 4, 5, 6].slice(4, 1)
371
- // []
372
- //
373
- // > [1, 2, 3, 4, 5, 6].slice(-100, 100)
374
- // [1, 2, 3, 4, 5, 6]
375
- // ```
376
- //
377
- // O(N)
378
- def slice[A](list: List[A], start: Int, stopExclusive: Int): List[A] = {
379
- val prefix = list.drop(start)
380
- val length = stopExclusive - start
381
- prefix.take(length)
382
- }
383
-
384
- // Split the list at given index.
385
- //
386
- // Law: `val (l, r) = list.splitAt(i); l.append(r) === list`
387
- //
388
- // O(N)
389
- def splitAt[A](list: List[A], index: Int): (List[A], List[A]) = {
390
- (list.take(index), list.drop(index))
391
- }
392
-
393
- // Update the element at given index in the list using the `update` function.
394
- // Returns the original list if the index is out of bounds.
395
- //
396
- // See: `modifyAt`
397
- // Examples:
398
- // ```
399
- // > [1, 2, 3].updateAt(1) { n => n + 100 }
400
- // [1, 102, 3]
401
- //
402
- // > [1, 2, 3].updateAt(10) { n => n + 100 }
403
- // [1, 2, 3]
404
- // ```
405
- //
406
- // O(N)
407
- def updateAt[A](list: List[A], index: Int) { update: A => A }: List[A] = {
408
- list.splitAt(index) match {
409
- case (left, Cons(x, right)) =>
410
- left.append(Cons(update(x), right))
411
- case _ => list
412
- }
413
- }
414
-
415
- // Modify the element at given index in the list using the `update` function.
416
- // Throws `OutOfBounds` if the index is out of bounds.
417
- //
418
- // See: `updateAt`
419
- // Examples:
420
- // ```
421
- // > [1, 2, 3].modifyAt(1) { n => n + 100 }
422
- // Some([1, 102, 3])
423
- //
424
- // > [1, 2, 3].modifyAt(10) { n => n + 100 }
425
- // None()
426
- // ```
427
- //
428
- // O(N)
429
- def modifyAt[A](list: List[A], index: Int) { update: A => A }: List[A] / Exception[OutOfBounds] = {
430
- list.splitAt(index) match {
431
- case (left, Cons(x, right)) =>
432
- left.append(Cons(update(x), right))
433
- case _ => do raise(OutOfBounds(), "Trying to modify an element outside the bounds of a list")
434
- }
435
- }
436
-
437
- // Delete the element at given index in the list.
438
- //
439
- // Example:
440
- // ```
441
- // > [1, 2, 3, 4].deleteAt(1)
442
- // [1, 3, 4]
443
- //
444
- // > [1, 2, 3, 4].deleteAt(-1)
445
- // [1, 2, 3, 4]
446
- //
447
- // > [1, 2, 3, 4].deleteAt(10)
448
- // [1, 2, 3, 4]
449
- // ```
450
- //
451
- // O(N)
452
- def deleteAt[A](list: List[A], index: Int): List[A] = {
453
- val left = list.slice(0, index)
454
- val right = list.slice(index + 1, list.size())
455
- left.append(right)
456
- }
457
-
458
- // Add an element at given index in the list.
459
- //
460
- // Examples:
461
- // ```
462
- // > [1, 2, 3].insert(-1, 0)
463
- // [0, 1, 2, 3]
464
- //
465
- // > [1, 2, 3].insert(0, 0)
466
- // [0, 1, 2, 3]
467
- //
468
- // > [1, 2, 3].insert(1, 0)
469
- // [1, 0, 2, 3]
470
- //
471
- // > [1, 2, 3].insert(3, 0)
472
- // [1, 2, 3, 0]
473
- //
474
- // > [1, 2, 3].insert(10, 0)
475
- // [1, 2, 3, 0]
476
- // ```
477
- //
478
- // O(N)
479
- def insert[A](list: List[A], index: Int, x: A): List[A] = {
480
- val (left, right) = list.splitAt(index)
481
- left.append(Cons(x, right))
482
- }
483
-
484
- // Replace an element at given index in the list.
485
- // Returns the original list when the index is out of bounds.
486
- //
487
- // Examples:
488
- // ```
489
- // > [1, 2, 3].replace(0, 42)
490
- // [42, 2, 3]
491
- //
492
- // > [1, 2, 3].replace(-1, 42)
493
- // [1, 2, 3]
494
- //
495
- // > [1, 2, 3].replace(10, 42)
496
- // [1, 2, 3]
497
- // ```
498
- //
499
- // O(N)
500
- def replace[A](list: List[A], index: Int, x: A): List[A] = {
501
- if (index < 0 || index >= list.size()) {
502
- list
503
- } else {
504
- val left = list.take(index)
505
- val right = list.drop(index + 1)
506
- left.append(Cons(x, right))
507
- }
508
- }
509
-
510
- // Produce a list of pairs from a pair of lists.
511
- // The length of the result is the minimum of lengths of the two lists.
512
- //
513
- // Examples:
514
- // ```
515
- // > zip([1, 2, 3], [100, 200, 300])
516
- // [(1, 100), (2, 200), (3, 300)]
517
- //
518
- // > zip([1, 2, 3], Nil[Int]())
519
- // []
520
- //
521
- // > zip(Nil[Int](), [1, 2, 3])
522
- // []
523
- //
524
- // > zip([1, 2, 3], [42])
525
- // [(1, 42)]
526
- // ```
527
- //
528
- // O(N)
529
- def zip[A, B](left: List[A], right: List[B]): List[(A, B)] = {
530
- def go(acc: List[(A, B)], left: List[A], right: List[B]): List[(A, B)] = {
531
- (left, right) match {
532
- case (Cons(a, as), Cons(b, bs)) =>
533
- val pair = (a, b)
534
- val newAcc = Cons(pair, acc)
535
- go(newAcc, as, bs)
536
- case _ => acc.reverse
537
- }
538
- }
539
- go(Nil(), left, right)
540
- }
541
-
542
- // Combine two lists with the given function.
543
- // The length of the result is the minimum of lengths of the two lists.
544
- //
545
- // Examples:
546
- // ```
547
- // > zipWith([1, 2, 3], [100, 200, 300]) { (a, b) => a + b }
548
- // [101, 202, 303]
549
- //
550
- // > zipWith([1, 2, 3], Nil[Int]()) { (a, b) => a + b }
551
- // []
552
- //
553
- // > zipWith(Nil[Int](), [1, 2, 3]) { (a, b) => a + b }
554
- // []
555
- //
556
- // > zipWith([1, 2, 3], [42]) { (a, b) => a + b }
557
- // [43]
558
- // ```
559
- //
560
- // O(N)
561
- def zipWith[A, B, C](left: List[A], right: List[B]) { combine : (A, B) => C }: List[C] = {
562
- def go(acc: List[C], left: List[A], right: List[B]): List[C] = {
563
- (left, right) match {
564
- case (Cons(a, as), Cons(b, bs)) =>
565
- val result = combine(a, b)
566
- val newAcc = Cons(result, acc)
567
- go(newAcc, as, bs)
568
- case _ => acc.reverse
569
- }
570
- }
571
- go(Nil(), left, right)
572
- }
573
-
574
- // Produce a pair of lists from a list of pairs.
575
- //
576
- // Examples:
577
- // ```
578
- // > [(1, 100), (2, 200), (3, 300)].unzip()
579
- // ([1, 2, 3], [100, 200, 300])
580
- // ```
581
- //
582
- // O(N)
583
- def unzip[A, B](pairs: List[(A, B)]): (List[A], List[B]) = {
584
- pairs match {
585
- case Nil() => (Nil(), Nil())
586
- case Cons((l, r), rest) =>
587
- val (left, right) = rest.unzip();
588
- (Cons(l, left), Cons(r, right))
589
- }
590
- }
591
-
592
- // Partition a given list into two lists.
593
- // The left list contains the elements that satsify the predicate,
594
- // the right list contains the elements that do not.
595
- //
596
- // O(N)
597
- def partition[A](l: List[A]) { pred: A => Boolean }: (List[A], List[A]) = {
598
- var lefts: List[A] = Nil()
599
- var rights: List[A] = Nil()
600
- l.foreach { el =>
601
- if (pred(el)) {
602
- lefts = Cons(el, lefts)
603
- } else {
604
- rights = Cons(el, rights)
605
- }
606
- }
607
-
608
- (lefts.reverse, rights.reverse)
609
- }
610
-
611
- // Sort a list using a given comparison function.
612
- //
613
- // Note: this implementation is not stacksafe!
614
- //
615
- // O(N log N)
616
- def sortBy[A](l: List[A]) { compare: (A, A) => Boolean }: List[A] =
617
- l match {
618
- case Nil() => Nil()
619
- case Cons(pivot, rest) =>
620
- val (lt, gt) = rest.partition { el => compare(el, pivot) };
621
- val leftSorted = sortBy(lt) { (a, b) => compare(a, b) }
622
- val rightSorted = sortBy(gt) { (a, b) => compare(a, b) }
623
- leftSorted.append(Cons(pivot, rightSorted))
624
- }
625
-
626
- def sort(l: List[Int]): List[Int] = l.sortBy { (a, b) => a < b }
627
- // def sort(l: List[Double]): List[Double] = l.sortBy { (a, b) => a < b }
628
- // Future work: ^ needs `le` for `Double`
629
-
630
- // Check if a list is sorted according to the given comparison function.
631
- //
632
- // O(N)
633
- def isSortedBy[A](list: List[A]) { compare: (A, A) => Boolean }: Boolean = {
634
- def go(list: List[A]): Boolean = {
635
- list match {
636
- case Nil() => true
637
- case Cons(x, Nil()) => true
638
- case Cons(x, Cons(y, rest)) =>
639
- val next = Cons(y, rest) // Future work: Replace this by an @-pattern!
640
- compare(x, y) && go(next)
641
- }
642
- }
643
- go(list)
644
- }
645
-
646
- // =========================================
647
- // `show` / `println` overloads for options:
648
- // =========================================
649
-
650
- def show[A](l: List[A]) { showA: A => String }: String = l match {
651
- case Nil() => "Nil()"
652
- case Cons(x, xs) => "Cons(" ++ showA(x) ++ ", " ++ show(xs){showA} ++ ")"
653
- }
654
- def show(l: List[Int]): String = show(l){e => show(e)}
655
- def show(l: List[Double]): String = show(l){e => show(e)}
656
- def show(l: List[Boolean]): String = show(l){e => show(e)}
657
- def show(l: List[String]): String = show(l){e => e}
658
-
659
- def println(l: List[Int]): Unit = {
660
- val s: String = show(l)
661
- println(s)
662
- }
663
- def println(l: List[Double]): Unit = {
664
- val s: String = show(l)
665
- println(s)
666
- }
667
- def println(l: List[Boolean]): Unit = {
668
- val s: String = show(l)
669
- println(s)
670
- }
671
- def println(l: List[String]): Unit = {
672
- val s: String = show(l)
673
- println(s)
674
- }
@@ -1,53 +0,0 @@
1
- module immutable/option
2
-
3
- import effekt
4
-
5
- type Option[A] {
6
- None();
7
- Some(value: A)
8
- }
9
-
10
- def isDefined[A](self: Option[A]): Boolean = self match {
11
- case None() => false
12
- case Some(v) => true
13
- }
14
-
15
- def isEmpty[A](self: Option[A]): Boolean =
16
- self.isDefined.not
17
-
18
- def orElse[A](self: Option[A]) { that: => Option[A] }: Option[A] = self match {
19
- case None() => that()
20
- case Some(v) => Some(v)
21
- }
22
-
23
- def getOrElse[A](self: Option[A]) { that: => A }: A = self match {
24
- case None() => that()
25
- case Some(v) => v
26
- }
27
-
28
- def map[A, B](self: Option[A]) { f: A => B }: Option[B] = self match {
29
- case None() => None()
30
- case Some(v) => Some(f(v))
31
- }
32
-
33
- def foreach[A](self: Option[A]) { f: A => Unit }: Unit = self match {
34
- case None() => ()
35
- case Some(v) => f(v)
36
- }
37
-
38
- // =========================================
39
- // `show` / `println` overloads for options:
40
- // =========================================
41
-
42
- // for now define some common cases; TODO better solution
43
- def show[A](o: Option[A]){ showA: A => String }: String = o match {
44
- case None() => "None()"
45
- case Some(v) => "Some(" ++ showA(v) ++ ")"
46
- }
47
- def show(o: Option[Int]): String = show(o){ e => show(e) }
48
- def show(o: Option[Double]): String = show(o){ e => show(e) }
49
- def show(o: Option[Boolean]): String = show(o){ e => show(e) }
50
-
51
- def println(o: Option[Int]): Unit = println(show(o))
52
- def println(o: Option[Double]): Unit = println(show(o))
53
- def println(o: Option[Boolean]): Unit = println(show(o))