@effekt-lang/effekt 0.47.0 → 0.49.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.
@@ -3,6 +3,7 @@ module list
3
3
  import effekt
4
4
  import option
5
5
  import exception
6
+ import stream
6
7
 
7
8
  /// Immutable linked list for finite sequences of elements.
8
9
  type List[A] {
@@ -167,9 +168,52 @@ def foreachIndex[A](list: List[A]){ f: (Int, A) {Control} => Unit }: Unit = {
167
168
  /// Map a function `f` over elements in a given list.
168
169
  ///
169
170
  /// O(N)
170
- def map[A, B](l: List[A]) { f: A => B } : List[B] = {
171
- var acc = Nil[B]()
172
- l.foreach { el => acc = Cons(f(el), acc) }
171
+ def map[A, B](l: List[A]) { f: A => B }: List[B] = {
172
+ var acc: List[B] = Nil()
173
+ l.foreach { el =>
174
+ acc = Cons(f(el), acc)
175
+ }
176
+ acc.reverse
177
+ }
178
+
179
+ /// Map a function `f` over elements and their indices in a given list.
180
+ ///
181
+ /// O(N)
182
+ def mapWithIndex[A, B](l: List[A]) { f: (Int, A) => B }: List[B] = {
183
+ var acc: List[B] = Nil()
184
+ l.foreachIndex { (i, el) =>
185
+ acc = Cons(f(i, el), acc)
186
+ }
187
+ acc.reverse
188
+ }
189
+
190
+ /// Map a function `f` over elements in a given list,
191
+ /// keeping only the elements for which the function returned `true`,
192
+ /// discarding the elements for which the function returned `false`.
193
+ ///
194
+ /// O(N)
195
+ def filter[A](l: List[A]) { shouldKeep: A => Bool }: List[A] = {
196
+ var acc: List[A] = Nil()
197
+ l.foreach { a =>
198
+ if (shouldKeep(a)) {
199
+ acc = Cons(a, acc)
200
+ }
201
+ }
202
+ acc.reverse
203
+ }
204
+
205
+ /// Map a function `f` over elements and their indices in a given list,
206
+ /// keeping only the elements for which the function returned `true`,
207
+ /// discarding the elements for which the function returned `false`.
208
+ ///
209
+ /// O(N)
210
+ def filterWithIndex[A](l: List[A]) { shouldKeep: (Int, A) => Bool }: List[A] = {
211
+ var acc: List[A] = Nil()
212
+ l.foreachIndex { (i, a) =>
213
+ if (shouldKeep(i, a)) {
214
+ acc = Cons(a, acc)
215
+ }
216
+ }
173
217
  acc.reverse
174
218
  }
175
219
 
@@ -178,13 +222,28 @@ def map[A, B](l: List[A]) { f: A => B } : List[B] = {
178
222
  /// discarding the elements for which the function returned `None()`.
179
223
  ///
180
224
  /// O(N)
181
- def collect[A, B](l: List[A]) { f : A => Option[B] }: List[B] = {
182
- var acc = Nil[B]()
225
+ def collectSome[A, B](l: List[A]) { f : A => Option[B] }: List[B] = {
226
+ var acc: List[B] = Nil()
183
227
  l.foreach { a =>
184
- val optB = f(a)
185
- optB match {
186
- case None() => ();
187
- case Some(b) => acc = Cons(b, acc);
228
+ f(a) match {
229
+ case None() => ()
230
+ case Some(b) => acc = Cons(b, acc)
231
+ }
232
+ }
233
+ acc.reverse
234
+ }
235
+
236
+ /// Map a function `f` over elements and their indices in a given list,
237
+ /// keeping only the elements for which the function returned `Some(...)`,
238
+ /// discarding the elements for which the function returned `None()`.
239
+ ///
240
+ /// O(N)
241
+ def collectWithIndex[A, B](l: List[A]) { f: (Int, A) => Option[B] }: List[B] = {
242
+ var acc: List[B] = Nil()
243
+ l.foreachIndex { (i, a) =>
244
+ f(i, a) match {
245
+ case None() => ()
246
+ case Some(b) => acc = Cons(b, acc)
188
247
  }
189
248
  }
190
249
  acc.reverse
@@ -205,21 +264,55 @@ def flatMap[A, B](l: List[A]) { f : A => List[B] }: List[B] = {
205
264
  /// Check if predicate is true for all elements of the given list.
206
265
  ///
207
266
  /// O(N)
208
- def all[A](list: List[A]) { predicate: A => Bool }: Bool = {
267
+ def all[A](list: List[A]) { predicate: A => Bool }: Bool =
209
268
  list match {
210
269
  case Cons(x, xs) => predicate(x) && all(xs) { predicate }
211
270
  case Nil() => true
212
271
  }
213
- }
214
272
 
215
273
  /// Check if predicate is true for at least one element of the given list.
216
274
  ///
217
275
  /// O(N)
218
- def any[A](list: List[A]) { predicate: A => Bool }: Bool = {
276
+ def any[A](list: List[A]) { predicate: A => Bool }: Bool =
219
277
  list match {
220
278
  case Cons(x, xs) => predicate(x) || any(xs) { predicate }
221
279
  case Nil() => false
222
280
  }
281
+
282
+ /// Check if the list contains the given `element`,
283
+ /// comparing for equality with the given `eq` function.
284
+ ///
285
+ /// O(N)
286
+ def contains[A](list: List[A], element: A) { eq: (A, A) => Bool }: Bool =
287
+ list.any { x => x.eq(element) }
288
+
289
+ /// Find the first index of the given `element`,
290
+ /// comparing for equality with the given `eq` function.
291
+ ///
292
+ /// O(N)
293
+ def indexOf[A](list: List[A], element: A) { eq: (A, A) => Bool }: Option[Int] = {
294
+ var result = None()
295
+ list.foreachIndex { (i, a) {label} =>
296
+ if (element.eq(a)) {
297
+ result = Some(i)
298
+ label.break()
299
+ }
300
+ }
301
+ result
302
+ }
303
+
304
+ /// Find the last index of the given `element`,
305
+ /// comparing for equality with the given `eq` function.
306
+ ///
307
+ /// O(N)
308
+ def lastIndexOf[A](list: List[A], element: A) { eq: (A, A) => Bool }: Option[Int] = {
309
+ var result = None()
310
+ list.foreachIndex { (i, a) {label} =>
311
+ if (element.eq(a)) {
312
+ result = Some(i)
313
+ }
314
+ }
315
+ result
223
316
  }
224
317
 
225
318
  /// Count how many elements of a list satisfy the given predicate.
@@ -297,10 +390,11 @@ def reverse[A](l: List[A]): List[A] = {
297
390
  /// ```
298
391
  ///
299
392
  /// O(|l|)
300
- def reverseOnto[A](l: List[A], other: List[A]): List[A] = l match {
301
- case Nil() => other
302
- case Cons(a, rest) => rest.reverseOnto(Cons(a, other))
303
- }
393
+ def reverseOnto[A](l: List[A], other: List[A]): List[A] =
394
+ l match {
395
+ case Nil() => other
396
+ case Cons(a, rest) => rest.reverseOnto(Cons(a, other))
397
+ }
304
398
 
305
399
  /// Concatenate list `l` with list `other`:
306
400
  ///
@@ -347,7 +441,7 @@ def join[A](lists: List[List[A]]): List[A] = {
347
441
  /// ```
348
442
  ///
349
443
  /// O(N)
350
- def join[A](lists: List[List[A]], between: List[A]): List[A] = {
444
+ def join[A](lists: List[List[A]], between: List[A]): List[A] =
351
445
  lists match {
352
446
  case Nil() => Nil()
353
447
  case Cons(firstList, restOfLists) =>
@@ -355,7 +449,6 @@ def join[A](lists: List[List[A]], between: List[A]): List[A] = {
355
449
  restOfLists.flatMap { list => between.append(list)}
356
450
  )
357
451
  }
358
- }
359
452
 
360
453
  /// Take the first `n` elements of a given list.
361
454
  ///
@@ -836,3 +929,46 @@ def println(l: List[Int]): Unit = println(show(l))
836
929
  def println(l: List[Double]): Unit = println(show(l))
837
930
  def println(l: List[Bool]): Unit = println(show(l))
838
931
  def println(l: List[String]): Unit = println(show(l))
932
+
933
+
934
+ // Streaming
935
+ // ---------
936
+
937
+ /// Turns a `list` into a producer of a push stream
938
+ /// by emitting each contained value left-to-right.
939
+ def each[A](list: List[A]): Unit / emit[A] =
940
+ list match {
941
+ case Nil() => ()
942
+ case Cons(head, tail) =>
943
+ do emit(head)
944
+ each(tail)
945
+ }
946
+
947
+ def feed[T, R](list: List[T]) { reader: () => R / read[T] }: R = {
948
+ var l = list
949
+ try {
950
+ reader()
951
+ } with read[T] {
952
+ resume {
953
+ l match {
954
+ case Nil() => do stop()
955
+ case Cons(value, rest) =>
956
+ l = rest
957
+ return value
958
+ }
959
+ }
960
+ }
961
+ }
962
+
963
+ def collect[A] { stream: () => Unit / emit[A] }: List[A] =
964
+ returning::collect[A, Unit]{stream}.second
965
+
966
+ namespace returning {
967
+ def collect[A, R] { stream: () => R / emit[A] }: (R, List[A]) =
968
+ try {
969
+ (stream(), Nil())
970
+ } with emit[A] { (v) =>
971
+ val (r, vs) = resume(());
972
+ (r, Cons(v, vs))
973
+ }
974
+ }
@@ -1,5 +1,7 @@
1
1
  module map
2
2
 
3
+ import stream
4
+
3
5
  /// Ordered finite immutable map, backed by balanced binary trees of logarithmic depth.
4
6
  record Map[K, V](tree: internal::Tree[K, V], compare: (K, K) => Ordering at {})
5
7
 
@@ -989,4 +991,36 @@ namespace internal {
989
991
 
990
992
  "[" ++ res ++ "]"
991
993
  }
992
- }
994
+ }
995
+
996
+
997
+ // Streaming
998
+ // ---------
999
+
1000
+ /// Turns a `map` into a producer of a push stream
1001
+ /// of `(key, value)` pairs by emitting each contained *in order*.
1002
+ def each[K, V](map: Map[K, V]): Unit / emit[(K, V)] =
1003
+ map.foreach { (k, v) => do emit((k, v)) }
1004
+
1005
+ /// Turns a `map` into a producer of a push stream
1006
+ /// of its keys by emitting each contained *in order*.
1007
+ def eachKey[K, V](map: Map[K, V]): Unit / emit[K] =
1008
+ map.foreach { (k, _v) => do emit(k) }
1009
+
1010
+ /// Turns a `map` into a producer of a push stream
1011
+ /// of its values by emitting each contained.
1012
+ def eachValue[K, V](map: Map[K, V]): Unit / emit[V] =
1013
+ map.foreach { (_k, v) => do emit(v) }
1014
+
1015
+ def collect[K, V](compare: (K, K) => Ordering at {}) { stream: () => Unit / emit[(K, V)] }: Map[K, V] =
1016
+ returning::collect[K, V, Unit](compare){stream}.second
1017
+
1018
+ namespace returning {
1019
+ def collect[K, V, R](compare: (K, K) => Ordering at {}) { stream: () => R / emit[(K, V)] }: (R, Map[K, V]) =
1020
+ try {
1021
+ (stream(), empty(compare))
1022
+ } with emit[(K, V)] { case (k, v) =>
1023
+ val (r, map) = resume(());
1024
+ (r, map.put(k, v))
1025
+ }
1026
+ }
@@ -103,7 +103,7 @@ def emptyQueue[T](initialCapacity: Int): Queue[T] at global = {
103
103
  tail.set(mod(tail.get + 1, capacity.get))
104
104
  }
105
105
  }
106
- queue
106
+ box queue
107
107
  }
108
108
 
109
109
  namespace examples {
@@ -1,6 +1,7 @@
1
1
  module random
2
2
 
3
3
  import stream
4
+ import io/filesystem
4
5
  import io/error
5
6
 
6
7
  /// Infinite pull stream of random bytes.
@@ -104,3 +104,7 @@ extern def set[T](ref: Ref[T], value: T) at global: Unit =
104
104
  ret %Pos zeroinitializer
105
105
  """
106
106
  vm "ref::set[T](Ref[T], T)"
107
+
108
+ /// Modifies the inner contents of the `ref` with a function `f`
109
+ def map[T](ref: Ref[T]) { f: T => T }: Unit =
110
+ ref.set(f(ref.get))
@@ -875,7 +875,7 @@ def map[A, B](seq: Seq[A]) { f: (A) {Control} => B }: Seq[B] = {
875
875
 
876
876
  // def iterate[A, R](seq: Seq[A]) { prog: {Iterator[A]} => R }: R = {
877
877
 
878
- // var k: Unit => Unit at {} = fun(unit: Unit) { () }
878
+ // var k: Unit => Unit at {} = box { () => () }
879
879
  // var v: Option[A] = None()
880
880
 
881
881
  // try { seq.each { el => do yield(el) } } with Generator[A] {
@@ -1,6 +1,7 @@
1
1
  module set
2
2
 
3
3
  import map
4
+ import stream
4
5
 
5
6
  /// Ordered finite immutable set, backed by balanced binary trees of logarithmic depth.
6
7
  record Set[A](tree: internal::Tree[A, Unit], compare: (A, A) => Ordering at {})
@@ -231,4 +232,26 @@ def intersection[A](s1: Set[A], s2: Set[A], compare: (A, A) => Ordering at {}):
231
232
  ///
232
233
  /// O(???)
233
234
  def intersection[A](s1: Set[A], s2: Set[A]): Set[A] =
234
- s1.intersection(s2, s1.compare)
235
+ s1.intersection(s2, s1.compare)
236
+
237
+
238
+ // Streaming
239
+ // ---------
240
+
241
+ /// Turns a `set` into a producer of a push stream
242
+ /// by emitting each contained *in order*.
243
+ def each[A](set: Set[A]): Unit / emit[A] =
244
+ set.foreach { x => do emit(x) }
245
+
246
+ def collect[A](compare: (A, A) => Ordering at {}) { stream: () => Unit / emit[A] }: Set[A] =
247
+ returning::collect[A, Unit](compare){stream}.second
248
+
249
+ namespace returning {
250
+ def collect[A, R](compare: (A, A) => Ordering at {}) { stream: () => R / emit[A] }: (R, Set[A]) =
251
+ try {
252
+ (stream(), empty(compare))
253
+ } with emit[A] { (v) =>
254
+ val (r, set) = resume(());
255
+ (r, set.insert(v))
256
+ }
257
+ }