From d11c2dc591eb2b11cc0b19f3d344222a7ecf3027 Mon Sep 17 00:00:00 2001 From: Magnus Madsen Date: Sat, 12 Sep 2026 20:01:25 +0200 Subject: [PATCH] feat: add Extras.DelayList and Extras.DelayMap, ported from the Flix standard library Ports the DelayList and DelayMap modules and their tests from the Flix compiler repository (main/src/library/, identical to the v0.75.3 release). The only change to each source file is the module name, now under Extras; the only change to the tests is the `use` lines pointing at the extras modules. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01YRutVsR79myxEkpYp7CCqA --- README.md | 2 + src/Extras.flix | 2 + src/Extras/DelayList.flix | 1353 ++++++++++++++++ src/Extras/DelayMap.flix | 857 ++++++++++ test/TestDelayList.flix | 3120 +++++++++++++++++++++++++++++++++++++ test/TestDelayMap.flix | 1829 ++++++++++++++++++++++ 6 files changed, 7163 insertions(+) create mode 100644 src/Extras/DelayList.flix create mode 100644 src/Extras/DelayMap.flix create mode 100644 test/TestDelayList.flix create mode 100644 test/TestDelayMap.flix diff --git a/README.md b/README.md index 6121732..4baf005 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ A collection of functionality that extend the official Flix library. ## Modules +- `Extras.DelayList` — a lazy list whose elements are computed on demand. +- `Extras.DelayMap` — a map whose values are computed on demand. - `Extras.Graph` — functions on directed graphs represented as collections of edges. - `Extras.Queue` — an immutable first-in, first-out queue. diff --git a/src/Extras.flix b/src/Extras.flix index 77bf825..79678c7 100644 --- a/src/Extras.flix +++ b/src/Extras.flix @@ -18,6 +18,8 @@ /// The `Extras` module is a collection of submodules that extend the official /// Flix library, each offering a self-contained piece of functionality: /// +/// - `Extras.DelayList` is a lazy list whose elements are computed on demand. +/// - `Extras.DelayMap` is a map whose values are computed on demand. /// - `Extras.Graph` is a library of functions on directed graphs represented /// as collections of edges. /// - `Extras.Queue` is an immutable first-in, first-out queue. diff --git a/src/Extras/DelayList.flix b/src/Extras/DelayList.flix new file mode 100644 index 0000000..56ce468 --- /dev/null +++ b/src/Extras/DelayList.flix @@ -0,0 +1,1353 @@ +/* + * Copyright 2021 Jakob Schneider Villumsen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pub mod Extras.DelayList { + use Math.Shuffle + + pub enum DelayList[a] { + case ENil + case ECons(a, DelayList[a]) + case LCons(a, Lazy[DelayList[a]]) + case LList(Lazy[DelayList[a]]) + } + + instance Eq[DelayList[a]] with Eq[a] { + pub def eq(l1: DelayList[a], l2: DelayList[a]): Bool = match (l1, l2) { + case (DelayList.ENil, DelayList.ENil) => true + case (DelayList.ECons(x, xs), DelayList.ECons(y, ys)) => if (x != y) false else xs == ys + case (DelayList.ECons(x, xs), DelayList.LCons(y, ys)) => if (x != y) false else xs == force ys + case (DelayList.LCons(x, xs), DelayList.ECons(y, ys)) => if (x != y) false else (force xs) == ys + case (DelayList.LCons(x, xs), DelayList.LCons(y, ys)) => if (x != y) false else (force xs) == force ys + case (DelayList.LList(xs), DelayList.LList(ys)) => (force xs) == force ys + case (l, DelayList.LList(ys)) => l == force ys + case (DelayList.LList(xs), l) => (force xs) == l + case _ => false + } + } + + instance Order[DelayList[a]] with Order[a] { + + /// + /// Compares `l1` and `l2` lexicographically. + /// + pub def compare(l1: DelayList[a], l2: DelayList[a]): Comparison = match (l1, l2) { + case (DelayList.ENil, DelayList.ENil) => Comparison.EqualTo + case (_, DelayList.ENil) => Comparison.GreaterThan + case (DelayList.ENil, _) => Comparison.LessThan + case (DelayList.LList(xs), DelayList.LList(ys)) => (force xs) <=> (force ys) + case (_, DelayList.LList(ys)) => l1 <=> (force ys) + case (DelayList.LList(xs), _) => (force xs) <=> l2 + case (DelayList.ECons(x, xs), DelayList.ECons(y, ys)) => + let cmp = x <=> y; + if (cmp == Comparison.EqualTo) xs <=> ys else cmp + case (DelayList.ECons(x, xs), DelayList.LCons(y, ys)) => + let cmp = x <=> y; + if (cmp == Comparison.EqualTo) xs <=> (force ys) else cmp + case (DelayList.LCons(x, xs), DelayList.ECons(y, ys)) => + let cmp = x <=> y; + if (cmp == Comparison.EqualTo) (force xs) <=> ys else cmp + case (DelayList.LCons(x, xs), DelayList.LCons(y, ys)) => + let cmp = x <=> y; + if (cmp == Comparison.EqualTo) (force xs) <=> (force ys) else cmp + } + } + + instance ToString[DelayList[a]] with ToString[a] { + pub def toString(l: DelayList[a]): String = DelayList.toString(l) + } + + instance Foldable[DelayList] { + pub def foldLeft(f: (b, a) -> b \ ef, s: b, l: DelayList[a]): b \ ef = DelayList.foldLeft(f, s, l) + pub def foldRight(f: (a, b) -> b \ ef, s: b, l: DelayList[a]): b \ ef = DelayList.foldRight(f, s, l) + redef head(l: DelayList[a]): Option[a] = DelayList.head(l) + redef isEmpty(l: DelayList[a]): Bool = DelayList.isEmpty(l) + redef memberOf(x: a, l: DelayList[a]): Bool with Eq[a] = DelayList.memberOf(x, l) + redef forAll(f: a -> Bool \ ef, l: DelayList[a]): Bool \ ef = DelayList.forAll(f, l) + redef exists(f: a -> Bool \ ef, l: DelayList[a]): Bool \ ef = DelayList.exists(f, l) + } + + instance UnorderedFoldable[DelayList] { + pub def foldMap(f: a -> b \ ef, l: DelayList[a]): b \ ef with CommutativeMonoid[b] = DelayList.foldMap(f, l) + redef isEmpty(l: DelayList[a]): Bool = DelayList.isEmpty(l) + redef exists(f: a -> Bool \ ef, l: DelayList[a]): Bool \ ef = DelayList.exists(f, l) + redef forAll(f: a -> Bool \ ef, l: DelayList[a]): Bool \ ef = DelayList.forAll(f, l) + redef memberOf(x: a, l: DelayList[a]): Bool with Eq[a] = DelayList.memberOf(x, l) + } + + instance Functor[DelayList] { + pub def map(f: a -> b \ ef, l: DelayList[a]): DelayList[b] \ ef = DelayList.map(f, l) + } + + instance Applicative[DelayList] { + pub def point(x: a): DelayList[a] = DelayList.singleton(x) + pub def ap(f: DelayList[a -> b \ ef], l: DelayList[a]): DelayList[b] \ ef = DelayList.ap(f, l) + } + + instance Monad[DelayList] { + pub def flatMap(f: a -> DelayList[b] \ ef, l: DelayList[a]): DelayList[b] \ ef = DelayList.flatMap(f, l) + } + + instance MonadZero[DelayList] { + pub def empty(): DelayList[a] = DelayList.empty() + } + + instance Traversable[DelayList] { + pub def traverse(f: a -> m[b] \ ef, l: DelayList[a]): m[DelayList[b]] \ ef with Applicative[m] = DelayList.traverse(f, l) + redef sequence(l: DelayList[m[a]]): m[DelayList[a]] with Applicative[m] = DelayList.sequence(l) + } + + instance Filterable[DelayList] { + pub def filterMap(f: a -> Option[b] \ ef, x: DelayList[a]): DelayList[b] \ ef = DelayList.filterMap(f, x) + redef filter(f: a -> Bool \ ef, x: DelayList[a]): DelayList[a] \ ef = DelayList.filter(f, x) + } + + instance Witherable[DelayList] + + instance SemiGroup[DelayList[a]] { + pub def combine(l1: DelayList[a], l2: DelayList[a]): DelayList[a] = DelayList.append(l1, l2) + } + + instance Monoid[DelayList[a]] { + pub def empty(): DelayList[a] = DelayList.ENil + } + + instance Iterable[DelayList[a]] { + type Elm = a + pub def iterator(rc: Region[r], l: DelayList[a]): Iterator[a, r, r] \ r = DelayList.iterator(rc, l) + } + + instance ForEach[DelayList[a]] { + type Elm = a + pub def forEach(f: a -> Unit \ ef, l: DelayList[a]): Unit \ ef = DelayList.forEach(f, l) + } + + /// + /// Returns a string representation of `l`. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def toString(l: DelayList[a]): String with ToString[a] = region rc { + "DelayList(" + (DelayList.iterator(rc, l) |> Iterator.join(", ")) + ")" + } + + /// + /// Returns an empty DelayList. + /// + @Experimental + pub def empty(): DelayList[a] = ENil + + /// + /// Returns true if and only if `l` is the empty DelayList, i.e. `ENil`. + /// + /// Does not force the tail of `l`. + /// + @Experimental + pub def isEmpty(l: DelayList[a]): Bool = match l { + case ENil => true + case LList(xs) => isEmpty(force xs) + case _ => false + } + + /// + /// Returns true if and only if `l` is a non-empty DelayList. + /// + /// Does not force the tail of `l`. + /// + @Experimental + pub def nonEmpty(l: DelayList[a]): Bool = not isEmpty(l) + + /// + /// Returns `Some(x)` if `x` is the first element of `l`. + /// + /// Returns `None` if `l` is empty. + /// + /// Does not force the tail of `l`. + /// + @Experimental + pub def head(l: DelayList[a]): Option[a] = match l { + case ENil => None + case ECons(x, _) => Some(x) + case LCons(x, _) => Some(x) + case LList(xs) => head(force xs) + } + + /// + /// Returns `Some(x)` if `x` is the last element of `l`. + /// + /// Returns `None` if `l` is empty. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def last(l: DelayList[a]): Option[a] = match l { + case ENil => None + case ECons(x, xs) => if (isEmpty(xs)) Some(x) else last(xs) + case LCons(x, xs) => if (isEmpty(force xs)) Some(x) else last(force xs) + case LList(xs) => last(force xs) + } + + /// + /// Returns `Some(xs)` where `xs` is `l` without the first element. + /// + /// Returns `None` if `l` is empty. + /// + /// Forces `l` until the first element is found, but does not force the tail. + /// + @Experimental + pub def tail(l: DelayList[a]): Option[DelayList[a]] = match l { + case ENil => None + case ECons(_, xs) => Some(xs) + case LCons(_, xs) => Some(LList(xs)) + case LList(xs) => tail(force xs) + } + + /// + /// Returns `Some(xs)` where `xs` is `l` without the last element. + /// + /// Returns `None` if `l` is empty. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def init(l: DelayList[a]): Option[DelayList[a]] = + def loop(prev, ll, acc) = match ll { + case ENil => acc + case ECons(x, xs) => loop(x, xs, ECons(prev, acc)) + case LCons(x, xs) => loop(x, force xs, ECons(prev, acc)) + case LList(xs) => loop(prev, force xs, acc) + }; + match l { + case ENil => None + case ECons(x, xs) => Some(reverse(loop(x, xs, ENil))) + case LCons(x, xs) => Some(reverse(loop(x, force xs, ENil))) + case LList(xs) => init(force xs) + } + + /// + /// Returns the number of elements in `l`. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def length(l: DelayList[a]): Int32 = + def loop(ll, acc) = match ll { + case ENil => acc + case ECons(_, xs) => loop(xs, acc + 1) + case LCons(_, xs) => loop(force xs, acc + 1) + case LList(xs) => loop(force xs, acc) + }; + loop(l, 0) + + /// + /// Returns the number of elements in `l`. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def size(l: DelayList[a]): Int32 = length(l) + + /// + /// Returns `l2` appended to `l1`. + /// + /// Does not force the tail of `l1`. + /// + @Experimental @Lazy + pub def append(l1: DelayList[a], l2: DelayList[a]): DelayList[a] = match l1 { + case ENil => l2 + case ECons(x, xs) => LCons(x, lazy append(xs, l2)) + case LCons(x, xs) => LCons(x, lazy append(force xs, l2)) + case LList(xs) => LList(lazy append(force xs, l2)) + } + + /// + /// Returns the number of elements in `l` that satisfy the predicate `f`. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def count(f: a -> Bool \ ef, l: DelayList[a]): Int32 \ ef = + foldLeft((i, x) -> if (f(x)) i + 1 else i, 0, l) + + /// + /// Returns the sum of all elements in the DelayList `l`. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def sum(l: DelayList[Int32]): Int32 = + Foldable.sum(l) + + /// + /// Returns the sum of all elements in the DelayList `l` according to the function `f`. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def sumWith(f: a -> Int32 \ ef, l: DelayList[a]): Int32 \ ef = + Foldable.sumWith(f, l) + + /// + /// Returns the concatenation of the elements in `l`. + /// + /// Does not force the tail of `l`. + /// + @Experimental @Lazy + pub def flatten(l: DelayList[DelayList[a]]): DelayList[a] = match l { + case ENil => ENil + case ECons(x, xs) => append(x, LList(lazy flatten(xs))) + case LCons(x, xs) => append(x, LList(lazy flatten(force xs))) + case LList(xs) => LList(lazy flatten(force xs)) + } + + /// + /// Returns `true` if and only if at least one element in `l` satisfies the predicate `f`. + /// + /// Returns `false` if `l` is empty. + /// + /// Forces elements of `l` until the predicate `f` is satisfied. + /// + @Experimental + pub def exists(f: a -> Bool \ ef, l: DelayList[a]): Bool \ ef = match l { + case ENil => false + case ECons(x, xs) => if (f(x)) true else exists(f, xs) + case LCons(x, xs) => if (f(x)) true else exists(f, force xs) + case LList(xs) => exists(f, force xs) + } + + /// + /// Returns `true` if and only if all elements in `l` satisfy the predicate `f`. + /// + /// Returns `true` if `l` is empty. + /// + /// Forces elements in `l` until the first element that does not satisfy the predicate `f` (inclusive). + /// + @Experimental + pub def forAll(f: a -> Bool \ ef, l: DelayList[a]): Bool \ ef = match l { + case ENil => true + case ECons(x, xs) => if (f(x)) forAll(f, xs) else false + case LCons(x, xs) => if (f(x)) forAll(f, force xs) else false + case LList(xs) => forAll(f, force xs) + } + + /// + /// Returns `true` if and only if `l` contains the element `x`. + /// + /// Forces elements until `x` is found. + /// + @Experimental + pub def memberOf(x: a, l: DelayList[a]): Bool with Eq[a] = match l { + case ENil => false + case ECons(x1, xs) => if (x1 == x) true else memberOf(x, xs) + case LCons(x1, xs) => if (x1 == x) true else memberOf(x, force xs) + case LList(xs) => memberOf(x, force xs) + } + + /// + /// Optionally finds the smallest element of `l` according to the `Order` on `a`. + /// + /// Returns `None` if `l` is empty. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def minimum(l: DelayList[a]): Option[a] with Order[a] = + reduceLeft(Order.min, l) + + /// + /// Optionally finds the smallest element of `l` according to the given comparator `cmp`. + /// + /// Returns `None` if `l` is empty. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def minimumBy(cmp: (a, a) -> Comparison, l: DelayList[a]): Option[a] = + reduceLeft(Order.minBy(cmp), l) + + /// + /// Optionally finds the largest element of `l` according to the `Order` on `a`. + /// + /// Returns `None` if `l` is empty. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def maximum(l: DelayList[a]): Option[a] with Order[a] = + reduceLeft(Order.max, l) + + /// + /// Optionally finds the largest element of `l` according to the given comparator `cmp`. + /// + /// Returns `None` if `l` is empty. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def maximumBy(cmp: (a, a) -> Comparison, l: DelayList[a]): Option[a] = + reduceLeft(Order.maxBy(cmp), l) + + /// + /// Returns a `DelayList` of all integers between `b` (inclusive) and `e` (exclusive). + /// + /// Returns an empty `DelayList` if `b >= e`. + /// + @Experimental @Lazy + pub def range(b: Int32, e: Int32): DelayList[Int32] = + def loop(i) = { + if (i >= e) + ENil + else + LCons(i, lazy loop(i + 1)) + }; + LList(lazy loop(b)) + + /// + /// Returns an infinite DelayList of repeating `x`s. + /// + @Experimental @Lazy + pub def repeat(x: a): DelayList[a] = + LCons(x, lazy repeat(x)) + + /// + /// Returns an infinite sequence of integers starting from and including `n`. + /// + @Experimental @Lazy + pub def startFrom(n: Int32): DelayList[Int32] = + def loop(i) = LCons(i, lazy loop(i + 1)); + LList(lazy loop(n)) + + /// + /// Returns the result of applying `f` to every element in `l`. + /// + /// Whether `f` is applied eagerly or lazily depends on its purity: + /// + /// - If `f` is pure then it is applied lazily (i.e. the tail is not forced). + /// - If `f` is impure then it is applied eagerly (i.e. the entire list `l` is forced). + /// + @Experimental @LazyWhenPure + pub def map(f: a -> b \ ef, l: DelayList[a]): DelayList[b] \ ef = + match purityOf(f) { + case Purity.Pure(g) => mapL(g, l) + case Purity.Impure(g) => mapE(g, l) + } + + /// + /// Returns the result of applying `f` to every element in `l`. + /// + /// Applies `f` lazily (i.e. the tail is not forced). + /// + @Lazy + def mapL(f: a -> b, l: DelayList[a]): DelayList[b] = match l { + case ENil => ENil + case ECons(x, xs) => LCons(f(x), lazy mapL(f, xs)) + case LCons(x, xs) => LCons(f(x), lazy mapL(f, force xs)) + case LList(xs) => LList(lazy mapL(f, force xs)) + } + + /// + /// Returns the result of applying `f` to every element in `l`. + /// + /// Applies `f` eagerly (i.e. the entire list `l` is forced). + /// + def mapE(f: a -> b \ ef, l: DelayList[a]): DelayList[b] \ ef = + def loop(ll, k) = match ll { + case ENil => k(ENil) + case ECons(x, xs) => + let x1 = f(x); + loop(xs, ks -> k(ECons(x1, ks))) + case LCons(x, xs) => + let x1 = f(x); + loop(force xs, ks -> k(ECons(x1, ks))) + case LList(xs) => + loop(force xs, k) + }; + loop(l, identity) + + /// + /// Returns the result of applying `f` to every element in `l` along with that element's index. + /// + /// That is, the result is of the form: `f(0, x0) :: f(1, x1) :: ...`. + /// + /// Whether `f` is applied eagerly or lazily depends on its purity: + /// + /// - If `f` is pure then it is applied lazily (i.e. the tail is not forced). + /// - If `f` is impure then it is applied eagerly (i.e. the entire list `l` is forced). + /// + @Experimental @LazyWhenPure + pub def mapWithIndex(f: (Int32, a) -> b \ ef, l: DelayList[a]): DelayList[b] \ ef = + match purityOf2(f) { + case Purity2.Pure(g) => mapWithIndexL(g, l) + case Purity2.Impure(g) => mapWithIndexE(g, l) + } + + /// + /// Returns the result of applying `f` to every element in `l` along with the element's index. + /// + /// Applies `f` lazily (i.e. the tail is not forced). + /// + @Lazy + def mapWithIndexL(f: (Int32, a) -> b, l: DelayList[a]): DelayList[b] = + def loop(ll, i) = match ll { + case ENil => ENil + case ECons(x, xs) => LCons(f(i, x), lazy loop(xs, i + 1)) + case LCons(x, xs) => LCons(f(i, x), lazy loop(force xs, i + 1)) + case LList(xs) => LList(lazy loop(force xs, i)) + }; + LList(lazy loop(l, 0)) + + /// + /// Returns the result of applying `f` to every element in `l` along with the element's index. + /// + /// Applies `f` eagerly (i.e. the entire list `l` is forced). + /// + def mapWithIndexE(f: (Int32, a) -> b \ ef, l: DelayList[a]): DelayList[b] \ ef = + def loop(ll, i, k) = match ll { + case ENil => k(ENil) + case ECons(x, xs) => + let x1 = f(i, x); + loop(xs, i + 1, ks -> k(ECons(x1, ks))) + case LCons(x, xs) => + let x1 = f(i, x); + loop(force xs, i + 1, ks -> k(ECons(x1, ks))) + case LList(xs) => loop(force xs, i, k) + }; + loop(l, 0, identity) + + /// + /// Returns the result of applying `f` to every element in `l` and concatenating the results. + /// + /// Whether `f` is applied eagerly or lazily depends on its purity: + /// + /// - If `f` is pure then it is applied lazily (i.e. the tail is not forced). + /// - If `f` is impure then it is applied eagerly (i.e. the entire list `l` is forced). + /// + @Experimental @LazyWhenPure + pub def flatMap(f: a -> DelayList[b] \ ef, l: DelayList[a]): DelayList[b] \ ef = + match purityOf(f) { + case Purity.Pure(g) => flatMapL(g, l) + case Purity.Impure(g) => flatMapE(g, l) + } + + /// + /// Returns the result of applying `f` to every element in `l` and concatenating the results. + /// + /// Applies `f` lazily (i.e. the tail is not forced). + /// + @Lazy + def flatMapL(f: a -> DelayList[b], l: DelayList[a]): DelayList[b] = match l { + case ENil => ENil + case ECons(x, xs) => append(f(x), LList(lazy flatMapL(f, xs))) + case LCons(x, xs) => append(f(x), LList(lazy flatMapL(f, force xs))) + case LList(xs) => LList(lazy flatMapL(f, force xs)) + } + + /// + /// Returns the result of applying `f` to every element in `l` and concatenating the results. + /// + /// Applies `f` eagerly (i.e. the entire list `l` is forced). + /// + def flatMapE(f: a -> DelayList[b] \ ef, l: DelayList[a]): DelayList[b] \ ef = + def loop(ll, k) = match ll { + case ENil => k(ENil) + case ECons(x, xs) => + let xs1 = f(x); + loop(xs, ks -> k(append(xs1, ks))) + case LCons(x, xs) => + let xs1 = f(x); + loop(force xs, ks -> k(append(xs1, ks))) + case LList(xs) => loop(force xs, k) + }; + loop(l, identity) + + /// + /// Return the singleton list with element `x`. + /// + @Experimental + pub def singleton(x: a): DelayList[a] = ECons(x, ENil) + + /// + /// Apply every function from `f` to every argument from `l` and return a list with all results. + /// For `f = f1, f2, ...` and `l = x1, x2, ...` the results appear in the order + /// `f1(x1), f1(x2), ..., f2(x1), f2(x2), ...`. + /// + /// Whether the i-th function in `f` (`fi`) is applied eagerly or lazily depends on its purity: + /// + /// - If `fi` is pure then it is applied lazily (i.e. the tail of `l` is not forced). + /// - If `fi` is impure then it is applied eagerly (i.e. the entire list `l` is forced). + /// + /// Note that this implies that ALL functions in `f` must be pure to avoid forcing `l`. + /// + @Experimental @LazyWhenPure + pub def ap(f: DelayList[a -> b \ ef], l: DelayList[a]): DelayList[b] \ ef = + flatMap(g -> map(g, l), f) + + /// + /// Reverses the list `l`. + /// + /// Does not force the tail of `l`. + /// + @Experimental @Lazy + pub def reverse(l: DelayList[a]): DelayList[a] = + def loop(ll, acc) = match ll { + case ENil => acc + case ECons(x, xs) => loop(xs, ECons(x, acc)) + case LCons(x, xs) => loop(force xs, ECons(x, acc)) + case LList(xs) => loop(force xs, acc) + }; + LList(lazy loop(l, ENil)) + + /// + /// Returns `l` with every occurrence of `src` replaced by `dst`. + /// + /// Does not force the tail of `l`. + /// + @Experimental @Lazy + pub def replace(src: {src = a}, dst: {dst = a}, l: DelayList[a]): DelayList[a] with Eq[a] = + map(e -> if (src#src == e) dst#dst else e, l) + + /// + /// Applies `f` to a start value `s` and all elements in `l` going from left to right. + /// + /// That is, the result is of the form: `f(...f(f(s, x1), x2)..., xn)`. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def foldLeft(f: (b, a) -> b \ ef, s: b, l: DelayList[a]): b \ ef = match l { + case ENil => s + case ECons(x, xs) => foldLeft(f, f(s, x), xs) + case LCons(x, xs) => foldLeft(f, f(s, x), force xs) + case LList(xs) => foldLeft(f, s, force xs) + } + + /// + /// Applies `f` to a start value `s` and all elements in `l` going from right to left. + /// + /// That is, the result is of the form: `f(x1, ...f(xn-1, f(xn, s))...)`. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def foldRight(f: (a, b) -> b \ ef, s: b, l: DelayList[a]): b \ ef = + def loop(ll, k) = match ll { + case ENil => k(s) + case ECons(x, xs) => loop(xs, ks -> k(f(x, ks))) + case LCons(x, xs) => loop(force xs, ks -> k(f(x, ks))) + case LList(xs) => loop(force xs, k) + }; + loop(l, x -> checked_ecast(x)) + + /// + /// Returns the result of mapping each element and combining the results. + /// + pub def foldMap(f: a -> b \ ef, l: DelayList[a]): b \ ef with Monoid[b] = + foldLeft((acc, x) -> Monoid.combine(acc, f(x)), Monoid.empty(), l) + + /// + /// Applies `f` to every element of `l`. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def forEach(f: a -> Unit \ ef, l: DelayList[a]): Unit \ ef = match l { + case ENil => () + case ECons(x, xs) => f(x); forEach(f, xs) + case LCons(x, xs) => f(x); forEach(f, force xs) + case LList(xs) => forEach(f, force xs) + } + + /// + /// Applies `f` to every element of `l` along with that element's index. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def forEachWithIndex(f: (Int32, a) -> Unit \ ef, l: DelayList[a]): Unit \ ef = region rc { + let ix = Ref.fresh(rc, 0); + let f1 = x -> { let i = Ref.get(ix); f(i, x); Ref.put(i + 1, ix) }; + forEach(f1, l) + } + + /// + /// Applies `f` to all elements in `l` going from left to right until a single value `v` is obtained. Returns `Some(v)`. + /// + /// That is, the result is of the form: `Some(f(...f(f(x1, x2), x3)..., xn))` + /// + /// Returns `None` if `l` is empty. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def reduceLeft(f: (a, a) -> a \ ef, l: DelayList[a]): Option[a] \ ef = match l { + case ENil => None + case ECons(x, xs) => Some(foldLeft(f, x, xs)) + case LCons(x, xs) => Some(foldLeft(f, x, force xs)) + case LList(xs) => reduceLeft(f, force xs) + } + + /// + /// Applies `f` to all elements in `l` going from right to left until a single value `v` is obtained. Returns `Some(v)`. + /// + /// That is, the result is of the form: `Some(f(x1, ...f(xn-2, f(xn-1, xn))...))` + /// + /// Returns `None` if `l` is empty. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def reduceRight(f: (a, a) -> a \ ef, l: DelayList[a]): Option[a] \ ef = + def loop(ll, k) = match ll { + case ECons(x, xs) => if (isEmpty(xs)) k(x) else loop(xs, ks -> k(f(x, ks))) + case LCons(x, xs) => if (isEmpty(force xs)) k(x) else loop(force xs, ks -> k(f(x, ks))) + case LList(xs) => loop(force xs, k) + case _ => unreachable!() + }; + if (isEmpty(l)) None else Some(loop(l, x -> checked_ecast(x))) + + /// + /// Returns a `DelayList` with every element in `l` that satisfies the predicate `f`. + /// + /// Whether `f` is applied eagerly or lazily depends on its purity: + /// + /// - If `f` is pure then it is applied lazily (i.e. the tail is not forced). + /// - If `f` is impure then it is applied eagerly (i.e. the entire list `l` is forced). + /// + @Experimental @LazyWhenPure + pub def filter(f: a -> Bool \ ef, l: DelayList[a]): DelayList[a] \ ef = + match purityOf(f) { + case Purity.Pure(g) => filterL(g, l) + case Purity.Impure(g) => filterE(g, l) + } + + /// + /// Returns a `DelayList` with every element in `l` that satisfies the predicate `f`. + /// + /// Applies `f` lazily (i.e. the tail is not forced). + /// + @Lazy + def filterL(f: a -> Bool, l: DelayList[a]): DelayList[a] = match l { + case ENil => ENil + case ECons(x, xs) => if (f(x)) LCons(x, lazy filterL(f, xs)) else LList(lazy filterL(f, xs)) + case LCons(x, xs) => if (f(x)) LCons(x, lazy filterL(f, force xs)) else LList(lazy filterL(f, force xs)) + case LList(xs) => LList(lazy filterL(f, force xs)) + } + + /// + /// Returns a `DelayList` with every element in `l` that satisfies the predicate `f`. + /// + /// Applies `f` eagerly (i.e. the entire list `l` is forced). + /// + def filterE(f: a -> Bool \ ef, l: DelayList[a]): DelayList[a] \ ef = + def loop(ll, k) = match ll { + case ENil => k(ENil) + case ECons(x, xs) => if (f(x)) loop(xs, ks -> k(ECons(x, ks))) else loop(xs, k) + case LCons(x, xs) => if (f(x)) loop(force xs, ks -> k(ECons(x, ks))) else loop(force xs, k) + case LList(xs) => loop(force xs, k) + }; + loop(l, identity) + + /// + /// Collects the results of applying the partial function `f` to every element in `l`. + /// + /// Whether `f` is applied eagerly or lazily depends on its purity: + /// + /// - If `f` is pure then it is applied lazily (i.e. the tail is not forced). + /// - If `f` is impure then it is applied eagerly (i.e. the entire list `l` is forced). + /// + @Experimental @LazyWhenPure + pub def filterMap(f: a -> Option[b] \ ef, l: DelayList[a]): DelayList[b] \ ef = + match purityOf(f) { + case Purity.Pure(g) => filterMapL(g, l) + case Purity.Impure(g) => filterMapE(g, l) + } + + /// + /// Helper function for `filterMap`. + /// + /// Collects the results of applying the partial function `f` to every element in `l`. + /// + /// Applies `f` lazily (i.e. the tail is not forced). + /// + @Lazy + def filterMapL(f: a -> Option[b], l: DelayList[a]): DelayList[b] = + def loop(ll) = match ll { + case ENil => ENil + case ECons(x, xs) => + match f(x) { + case None => loop(xs) + case Some(v) => LCons(v, lazy loop(xs)) + } + case LCons(x, xs) => + // Same as above except `xs` is forced. + match f(x) { + case None => loop(force xs) + case Some(v) => LCons(v, lazy loop(force xs)) + } + case LList(xs) => LList(lazy loop(force xs)) + }; + LList(lazy loop(l)) + + /// + /// Helper function for `filterMap`. + /// + /// Collects the results of applying the partial function `f` to every element in `l`. + /// + /// Applies `f` eagerly (i.e. the entire list `l` is forced). + /// + def filterMapE(f: a -> Option[b] \ ef, l: DelayList[a]): DelayList[b] \ ef = + def loop(ll, k) = match ll { + case ENil => k(ENil) + case ECons(x, xs) => match f(x) { + case None => loop(xs, k) + case Some(v) => loop(xs, ks -> k(ECons(v, ks))) + } + case LCons(x, xs) => match f(x) { + // Same as above except `xs` is forced. + case None => loop(force xs, k) + case Some(v) => loop(force xs, ks -> k(ECons(v, ks))) + } + case LList(xs) => loop(force xs, k) + }; + loop(l, identity) + + /// + /// Optionally returns the first element of `l` that satisfies the predicate `f` when searching from left to right. + /// + /// Forces elements of `l` until the predicate `f` is satisfied. + /// + @Experimental + pub def findLeft(f: a -> Bool \ ef, l: DelayList[a]): Option[a] \ ef = match l { + case ENil => None + case ECons(x, xs) => if (f(x)) Some(x) else findLeft(f, xs) + case LCons(x, xs) => if (f(x)) Some(x) else findLeft(f, force xs) + case LList(xs) => findLeft(f, force xs) + } + + /// + /// Optionally returns the first element of `l` that satisfies the predicate `f` when searching from right to left. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def findRight(f: a -> Bool \ ef, l: DelayList[a]): Option[a] \ ef = + def loop(ll, k) = match ll { + case ENil => k() + case ECons(x, xs) => loop(xs, () -> if (f(x)) Some(x) else k()) + case LCons(x, xs) => loop(force xs, () -> if (f(x)) Some(x) else k()) + case LList(xs) => loop(force xs, k) + }; + loop(l, _ -> checked_ecast(None)) + + /// + /// Returns the first non-None result of applying the partial function `f` to each element of `l`. + /// + /// Returns `None` if every element `f(x)` of `l` is `None`. + /// + /// Forces elements of `l` until `f(x)` returns `Some(v)`. + /// + @Experimental + pub def findMap(f: a -> Option[b] \ ef, l: DelayList[a]): Option[b] \ ef = match l { + case ENil => None + case ECons(x, xs) => match f(x) { + case None => findMap(f, xs) + case Some(v) => Some(v) + } + case LCons(x, xs) => match f(x) { + // Same as above except `xs` is forced. + case None => findMap(f, force xs) + case Some(v) => Some(v) + } + case LList(xs) => findMap(f, force xs) + } + + /// + /// Returns `l` with `x` inserted between every two adjacent elements. + /// + /// Does not force the tail of `l`. + /// + @Experimental @Lazy + pub def intersperse(x: a, l: DelayList[a]): DelayList[a] = match l { + case ENil => ENil + case ECons(x1, xs) => if (isEmpty(xs)) l else LCons(x1, lazy LCons(x, lazy intersperse(x, xs))) + case LCons(x1, xs) => if (isEmpty(force xs)) l else LCons(x1, lazy LCons(x, lazy intersperse(x, force xs))) + case LList(xs) => LList(lazy intersperse(x, force xs)) + } + + /// + /// Returns the concatenation of the elements in `l2` with the elements + /// of `l1` inserted between every two adjacent elements of `l2`. + /// + /// That is, returns `l2.1 :: l1.1 ... l1.n :: l2.2 :: ... :: l2.n-1 :: l1.1 :: ... :: l1.n :: l2.n :: ENil`. + /// + /// Does not force the tail of `l2`. + /// + @Experimental @Lazy + pub def intercalate(l1: DelayList[a], l2: DelayList[DelayList[a]]): DelayList[a] = match l2 { + case ENil => ENil + case ECons(x, xs) => if (isEmpty(xs)) x else append(append(x, l1), intercalate(l1, xs)) + case LCons(x, xs) => if (isEmpty(force xs)) x else append(append(x, l1), intercalate(l1, force xs)) + case LList(xs) => LList(lazy intercalate(l1, force xs)) + } + + /// + /// Returns a pair of lists `(l1, l2)` where: + /// - `l1` contains all elements of `l` that satisfy the predicate `f`. + /// - `l2` contains all elements of `l` that DO NOT satisfy the predicate `f`. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def partition(f: a -> Bool \ ef, l: DelayList[a]): (DelayList[a], DelayList[a]) \ ef = + def loop(ll, k) = match ll { + case ENil => k((ENil, ENil)) + case ECons(x, xs) => + if (f(x)) + loop(xs, match (ks, ls) -> k((ECons(x, ks), ls))) + else + loop(xs, match (ks, ls) -> k((ks, ECons(x, ls)))) + case LCons(x, xs) => + // Same as above except `xs` is forced. + if (f(x)) + loop(force xs, match (ks, ls) -> k((ECons(x, ks), ls))) + else + loop(force xs, match (ks, ls) -> k((ks, ECons(x, ls)))) + case LList(xs) => loop(force xs, k) + }; + loop(l, identity) + + /// + /// Returns a pair of lists `(l1, l2)` where: + /// - `l1` is the longest prefix of `l` that satisfies the predicate `f`. + /// - `l2` is the remainder of `l`. + /// + /// Whether `f` is applied eagerly or lazily depends on its purity: + /// + /// - If `f` is pure then it is applied lazily (i.e. the tail is not forced). + /// - If `f` is impure then it is applied eagerly (i.e. the entire list `l` is forced). + /// + @Experimental @LazyWhenPure + pub def span(f: a -> Bool \ ef, l: DelayList[a]): (DelayList[a], DelayList[a]) \ ef = + match purityOf(f) { + case Purity.Pure(g) => spanL(g, l) + case Purity.Impure(g) => spanE(g, l) + } + + /// + /// Helper function for `span`. + /// + /// Applies `f` lazily (i.e. the tail is not forced). + /// + @Lazy + def spanL(f: a -> Bool, l: DelayList[a]): (DelayList[a], DelayList[a]) = match l { + case ENil => (ENil, ENil) + case ECons(x, xs) => + if (f(x)) + let t = lazy spanL(f, xs); + (LCons(x, lazy fst(force t)), LList(lazy snd(force t))) + else + (ENil, l) + case LCons(x, xs) => + // Same as above except `xs` is forced. + if (f(x)) + let t = lazy spanL(f, force xs); + (LCons(x, lazy fst(force t)), LList(lazy snd(force t))) + else + (ENil, l) + case LList(xs) => spanL(f, force xs) + } + + /// + /// Helper function for `span`. + /// + /// Applies `f` eagerly (i.e. the entire list `l` is forced). + /// + def spanE(f: a -> Bool \ ef, l: DelayList[a]): (DelayList[a], DelayList[a]) \ ef = + def loop(ll, k) = match ll { + case ENil => k((ENil, ENil)) + case ECons(x, xs) => + if (f(x)) + loop(xs, match (ks, ls) -> k((ECons(x, ks), ls))) + else + k((ENil, l)) + case LCons(x, xs) => + // Same as above except `xs` is forced. + if (f(x)) + loop(force xs, match (ks, ls) -> k((ECons(x, ks), ls))) + else + k((ENil, l)) + case LList(xs) => loop(force xs, k) + }; + loop(l, identity) + + /// + /// Returns `l` without the first `n` elements. + /// + /// Returns `ENil` if `n > length(l)`. + /// Returns `l` if `n < 1`. + /// + /// Does not force the tail of `l`. + /// + @Experimental @Lazy + pub def drop(n: Int32, l: DelayList[a]): DelayList[a] = + def loop(i, ll) = { + // Inner function used here to allow for early termination + if (i < 1) + ll + else + match ll { + case ENil => ll + case ECons(_, xs) => loop(i - 1, xs) + case LCons(_, xs) => loop(i - 1, force xs) + case LList(xs) => loop(i, force xs) + } + }; + LList(lazy loop(n, l)) + + /// + /// Returns `l` without the longest prefix that satisfies the predicate `f`. + /// + /// Whether `f` is applied eagerly or lazily depends on its purity: + /// + /// - If `f` is pure then it is applied lazily (i.e. the tail is not forced). + /// - If `f` is impure then it is applied eagerly (i.e. the tail is forced until the first element that satisfies `f`). + /// + @Experimental @LazyWhenPure + pub def dropWhile(f: a -> Bool \ ef, l: DelayList[a]): DelayList[a] \ ef = + match purityOf(f) { + case Purity.Pure(g) => dropWhileL(g, l) + case Purity.Impure(g) => dropWhileE(g, l) + } + + /// + /// Helper function for `dropWhile`. + /// + /// Returns `l` without the longest prefix that satisfies the predicate `f`. + /// + /// Applies `f` lazily (i.e. the tail is not forced). + /// + @Lazy + def dropWhileL(f: a -> Bool, l: DelayList[a]): DelayList[a] = + def loop(ll) = match ll { + // Inner function used here to allow for early termination + case ENil => ENil + case ECons(x, xs) => if (f(x)) loop(xs) else ll + case LCons(x, xs) => if (f(x)) loop(force xs) else ll + case LList(xs) => loop(force xs) + }; + LList(lazy loop(l)) + + /// + /// Helper function for `dropWhile`. + /// + /// Returns `l` without the longest prefix that satisfies the predicate `f`. + /// + /// Applies `f` eagerly (i.e. the tail is forced until the first element that satisfies `f`). + /// + def dropWhileE(f: a -> Bool \ ef, l: DelayList[a]): DelayList[a] \ ef = match l { + case ENil => ENil + case ECons(x, xs) => if (f(x)) dropWhileE(f, xs) else l + case LCons(x, xs) => if (f(x)) dropWhileE(f, force xs) else l + case LList(xs) => dropWhileE(f, force xs) + } + + /// + /// Returns the first `n` elements of `l`. + /// + /// Does not force the tail of `l`. + /// + @Experimental @Lazy + pub def take(n: Int32, l: DelayList[a]): DelayList[a] = + def loop(i, ll) = { + // Inner function used here to allow for early termination + if (i <= 0) + ENil + else + match ll { + case ENil => ENil + case ECons(x, xs) => LCons(x, lazy loop(i - 1, xs)) + case LCons(x, xs) => LCons(x, lazy loop(i - 1, force xs)) + case LList(xs) => loop(i, force xs) + } + }; + LList(lazy loop(n, l)) + + /// + /// Returns the longest prefix of `l` that satisfies the predicate `f`. + /// + /// Whether `f` is applied eagerly or lazily depends on its purity: + /// + /// - If `f` is pure then it is applied lazily (i.e. the tail is not forced). + /// - If `f` is impure then it is applied eagerly (i.e. the tail is forced until the first element that satisfies `f`). + /// + @Experimental @LazyWhenPure + pub def takeWhile(f: a -> Bool \ ef, l: DelayList[a]): DelayList[a] \ ef = + match purityOf(f) { + case Purity.Pure(g) => takeWhileL(g, l) + case Purity.Impure(g) => takeWhileE(g, l) + } + + /// + /// Helper function for `takeWhile`. + /// + /// Returns the longest prefix of `l` that satisfies the predicate `f`. + /// + /// Applies `f` lazily (i.e. the tail is not forced). + /// + @Lazy + def takeWhileL(f: a -> Bool, l: DelayList[a]): DelayList[a] = + def loop(ll) = match ll { + // Inner function used here to allow for early termination + case ENil => ENil + case ECons(x, xs) => if (f(x)) LCons(x, lazy loop(xs)) else ENil + case LCons(x, xs) => if (f(x)) LCons(x, lazy loop(force xs)) else ENil + case LList(xs) => loop(force xs) + }; + LList(lazy loop(l)) + + /// + /// Helper function for `takeWhile`. + /// + /// Returns the longest prefix of `l` that satisfies the predicate `f`. + /// + /// Applies `f` eagerly (i.e. the tail is forced until the first element that satisfies `f`). + /// + def takeWhileE(f: a -> Bool \ ef, l: DelayList[a]): DelayList[a] \ ef = + def loop(ll, k) = match ll { + case ENil => k(ENil) + case ECons(x, xs) => if (f(x)) loop(xs, ks -> k(ECons(x, ks))) else k(ENil) + case LCons(x, xs) => if (f(x)) loop(force xs, ks -> k(ECons(x, ks))) else k(ENil) + case LList(xs) => loop(force xs, k) + }; + loop(l, identity) + + /// + /// Returns a list where the element at index `i` is `(a, b)` where + /// `a` is the element at index `i` in `l1` and `b` is the element at index `i` in `l2`. + /// + /// If either `l1` or `l2` is depleted, then no further elements are added to the resulting list. + /// + /// Does not force the tail of either `l1` or `l2`. + /// + @Experimental @Lazy + pub def zip(l1: DelayList[a], l2: DelayList[b]): DelayList[(a, b)] = + def loop(ll1, ll2) = match (ll1, ll2) { + // Inner function used here to allow for early termination + case (ENil, _) => ENil + case (_, ENil) => ENil + case (ECons(x, xs), ECons(y, ys)) => LCons((x, y), lazy loop(xs, ys)) + case (ECons(x, xs), LCons(y, ys)) => LCons((x, y), lazy loop(xs, force ys)) + case (LCons(x, xs), ECons(y, ys)) => LCons((x, y), lazy loop(force xs, ys)) + case (LCons(x, xs), LCons(y, ys)) => LCons((x, y), lazy loop(force xs, force ys)) + case (LList(xs), LList(ys)) => LList(lazy loop(force xs, force ys)) + case (xs, LList(ys)) => LList(lazy loop(xs, force ys)) + case (LList(xs), ys) => LList(lazy loop(force xs, ys)) + }; + match (l1, l2) { + case (ENil, _) => ENil + case (_, ENil) => ENil + case _ => LList(lazy loop(l1, l2)) + } + + /// + /// Returns a list where the element at index `i` is `f(a, b)` where + /// `a` is the element at index `i` in `l1` and `b` is the element at index `i` in `l2`. + /// + /// If either `l1` or `l2` is depleted, then no further elements are added to the resulting list. + /// + /// Whether `f` is applied eagerly or lazily depends on its purity: + /// + /// - If `f` is pure then it is applied lazily (i.e. the tails are not forced). + /// - If `f` is impure then it is applied eagerly (i.e. both lists `l1` and `l2` are forced). + /// + @Experimental @LazyWhenPure + pub def zipWith(f: (a, b) -> c \ ef, l1: DelayList[a], l2: DelayList[b]): DelayList[c] \ ef = + map(x -> f(fst(x), snd(x)), zip(l1, l2)) + + /// + /// Returns a `DelayList` where each element `e` is mapped to `(i, e)` where `i` + /// is the index of `e`. + /// + /// Does not force the tail of `l`. + /// + pub def zipWithIndex(l: DelayList[a]): DelayList[(Int32, a)] = + def loop(ll, i) = match ll { + case ENil => ENil + case ECons(x, xs) => LCons(((i, x)), lazy loop(xs, i + 1)) + case LCons(x, xs) => LCons(((i, x)), lazy loop(force xs, i + 1)) + case LList(xs) => LList(lazy loop(force xs, i)) + }; + loop(l, 0) + + /// + /// Returns `l` as an `Array`. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def toArray(rc: Region[r], l: DelayList[a]): Array[a, r] \ r = + let a = Array.empty(rc, length(l)); + forEach(match (i, y) -> Array.put(y, i, a), zipWithIndex(l)); + a + + /// + /// Returns `l` as a Vector. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def toVector(l: DelayList[a]): Vector[a] = region rc { + let arr = Array.empty(rc, length(l)); + forEach(match (i, x) -> Array.put(x, i, arr), zipWithIndex(l)); + Array.toVector(arr) + } + + /// + /// Returns `l` as an `Iterator`. + /// + /// Does not force any elements of the list. + /// + @Experimental @Lazy + pub def iterator(rc: Region[r], l: DelayList[a]): Iterator[a, r, r] \ r = + let cursor = Ref.fresh(rc, l); + let next = () -> { + let ll = Ref.get(cursor); + match head(ll) { + case None => None + case Some(x) => + Ref.put(Option.getWithDefault(ENil, tail(ll)), cursor); + Some(x) + } + }; + Iterator.unfoldWithIter(rc, next) + + /// + /// Returns `l` as a `List`. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def toList(l: DelayList[a]): List[a] = + def loop(ll, k) = match ll { + case ENil => k(Nil) + case ECons(x, xs) => loop(xs, ks -> k(x :: ks)) + case LCons(x, xs) => loop(force xs, ks -> k(x :: ks)) + case LList(xs) => loop(force xs, k) + }; + loop(l, identity) + + /// + /// Returns the association list `l` as a map. + /// + /// If `l` contains multiple mappings with the same key, `toMap` does not + /// make any guarantees about which mapping will be in the resulting map. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def toMap(l: DelayList[(a, b)]): Map[a, b] with Order[a] = + def loop(ll, acc) = match ll { + case ENil => acc + case ECons((k, v), xs) => loop(xs, Map.insert(k, v, acc)) + case LCons((k, v), xs) => loop(force xs, Map.insert(k, v, acc)) + case LList(xs) => loop(force xs, acc) + }; + loop(l, Map.empty()) + + /// + /// Returns `l` as a `Set`. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def toSet(l: DelayList[a]): Set[a] with Order[a] = + def loop(ll, acc) = match ll { + case ENil => acc + case ECons(x, xs) => loop(xs, Set.insert(x, acc)) + case LCons(x, xs) => loop(force xs, Set.insert(x, acc)) + case LList(xs) => loop(force xs, acc) + }; + loop(l, Set.empty()) + + /// + /// Returns the concatenation of the string representation + /// of each element in `l` with `sep` inserted between each element. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def join(sep: String, l: DelayList[a]): String with ToString[a] = + Foldable.join(sep, l) + + /// + /// Returns the concatenation of the string representation + /// of each element in `l` according to `f` with `sep` inserted between each element. + /// + /// Forces the entire list `l`. + /// + @Experimental + pub def joinWith(f: a -> String \ ef, sep: String, l: DelayList[a]): String \ ef = + Foldable.joinWith(f, sep, l) + + /// + /// Helper function for `traverse` and `sequence`. + /// + /// Builds an "applicative DelayList" from a head of one applicative action and an + /// applicative DelayList of the tail. + /// + @Experimental + def consA(mx: f[a], ml: f[DelayList[a]]): f[DelayList[a]] with Applicative[f] = + (((x, xs) -> ECons(x, xs)) `Functor.map` mx) `Applicative.ap` ml + + /// + /// Returns the result of running all the actions in the DelayList `l`. + /// + @Experimental + pub def sequence(l: DelayList[m[a]]): m[DelayList[a]] with Applicative[m] = + def loop(ll, k) = match ll { + case ENil => k(Applicative.point(ENil)) + case ECons(mx, xs) => loop(xs, ks -> k(consA(mx, ks))) + case LCons(mx, xs) => loop(force xs, ks -> k(consA(mx, ks))) + case LList(xs) => loop(force xs, k) + }; + loop(l, identity) + + /// + /// Returns the result of applying the applicative mapping function `f` to all the elements of the + /// DelayList `l`. + /// + @Experimental + pub def traverse(f: a -> m[b] \ ef, l: DelayList[a]): m[DelayList[b]] \ ef with Applicative[m] = + def loop(ll, k) = match ll { + case ENil => k(Applicative.point(ENil)) + case ECons(x, xs) => { let ans = f(x); loop(xs, ks -> k(consA(ans, ks))) } + case LCons(x, xs) => { let ans = f(x); loop(force xs, ks -> k(consA(ans, ks))) } + case LList(xs) => loop(force xs, k) + }; + loop(l, identity) + + /// + /// Shuffles `l` using the Fisher–Yates shuffle. + /// + pub def shuffle(l: DelayList[a]): DelayList[a] \ Shuffle = region rc { + def fromList(xs) = match xs { + case Nil => ENil + case y :: ys => ECons(y, fromList(ys)) + }; + toArray(rc, l) !> Array.shuffle |> Array.toList |> fromList + } + +} diff --git a/src/Extras/DelayMap.flix b/src/Extras/DelayMap.flix new file mode 100644 index 0000000..48e42cf --- /dev/null +++ b/src/Extras/DelayMap.flix @@ -0,0 +1,857 @@ +/* + * Copyright 2021 Jakob Schneider Villumsen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pub mod Extras.DelayMap { + + import java.lang.Runtime + + pub enum DelayMap[k, v] { + case DMap(RedBlackTree[k, Lazy[v]]) + } + + instance Eq[DelayMap[k, v]] with Eq[k], Eq[v] { + pub def eq(m1: DelayMap[k, v], m2: DelayMap[k, v]): Bool = + DelayMap.toList(m1) == DelayMap.toList(m2) + } + + instance Order[DelayMap[k, v]] with Order[k], Order[v] { + pub def compare(x: DelayMap[k, v], y: DelayMap[k, v]): Comparison = + DelayMap.toList(x) <=> DelayMap.toList(y) + } + + instance ToString[DelayMap[k, v]] with ToString[k], ToString[v] { + pub def toString(m: DelayMap[k, v]): String = DelayMap.toString(m) + } + + instance Indexable[DelayMap[k, v]] with Order[k] { + type Idx = k + type Elm = v + type Aef = KeyNotFound + pub def get(t: DelayMap[k, v], i: k): v \ KeyNotFound = match DelayMap.get(i, t) { + case Some(v) => v + case None => KeyNotFound.keyNotFound("key not found") + } + } + + instance Functor[DelayMap[k]] { + pub def map(f: v1 -> v2 \ ef, m: DelayMap[k, v1]): DelayMap[k, v2] \ ef = DelayMap.map(f, m) + } + + instance Foldable[DelayMap[k]] { + pub def foldLeft(f: (b, v) -> b \ ef, s: b, m: DelayMap[k, v]): b \ ef = DelayMap.foldLeft(f, s, m) + pub def foldRight(f: (v, b) -> b \ ef, s: b, m: DelayMap[k, v]): b \ ef = DelayMap.foldRight(f, s, m) + redef isEmpty(m: DelayMap[k, v]): Bool = DelayMap.isEmpty(m) + + } + + instance Iterable[DelayMap[k, v]] { + type Elm = (k, v) + pub def iterator(rc: Region[r], m: DelayMap[k, v]): Iterator[(k, v), r, r] \ r = + DelayMap.iterator(rc, m) + } + + instance ForEach[DelayMap[k, v]] { + type Elm = (k, v) + pub def forEach(f: ((k, v)) -> Unit \ ef, m: DelayMap[k, v]): Unit \ ef = DelayMap.forEach(k -> v -> f((k, v)), m) + } + + /// + /// Returns a string representation of the given `DelayMap` `m`. + /// + @Experimental + pub def toString(m: DelayMap[k, v]): String with ToString[k], ToString[v] = region rc { + "DelayMap#{" + (DelayMap.iterator(rc, m) |> Iterator.map(match (k, v) -> "${k} => ${v}") |> Iterator.join(", ")) + "}" + } + + /// + /// Returns the number of threads to use for parallel evaluation. + /// + /// # SAFETY: + /// This accesses the runtime environment, which is an effect. + /// It is assumed that this function is only used in contexts + /// where this effect is not observable outside of the DelayMap module. + /// + def threads(): Int32 = { + // Note: We use a multiple of the number of physical cores for better performance. + let multiplier = 4; + multiplier * Runtime.getRuntime().availableProcessors() + } + + /// + /// Determines whether to use parallel evaluation. + /// + /// By default we only enable parallel evaluation if the map has a certain size. + /// + def useParallelEvaluation(m: DelayMap[k, v]): Bool = + let DMap(t) = m; + let minSize = Int32.pow(base = 2, RedBlackTree.blackHeight(t)); + minSize >= 1024 + + /// + /// Returns the empty map. + /// + @Experimental + pub def empty(): DelayMap[k, v] = + DMap(RedBlackTree.empty()) + + /// + /// Returns the singleton map where key `k` is mapped to value `v`. + /// + @Experimental + pub def singleton(k: k, v: v): DelayMap[k, v] with Order[k] = + insert(k, v, empty()) + + /// + /// Returns the number of keys in `m`. + /// + @Experimental + pub def size(m: DelayMap[k, v]): Int32 = + let DMap(t) = m; + RedBlackTree.size(t) + + /// + /// Returns `true` if and only if `m` is the empty map, i.e. `Map(Nil)`. + /// + @Experimental + pub def isEmpty(m: DelayMap[k, v]): Bool = + let DMap(t) = m; + RedBlackTree.isEmpty(t) + + /// + /// Returns `true` if and only if `m` is a non-empty map. + /// + @Experimental + pub def nonEmpty(m: DelayMap[k, v]): Bool = not isEmpty(m) + + /// + /// Returns `m` with `k => v`. + /// + @Experimental + pub def insert(k: k, v: v, m: DelayMap[k, v]): DelayMap[k, v] with Order[k] = + let DMap(t) = m; + DMap(RedBlackTree.insert(k, lazy v, t)) + + /// + /// Returns `Some(v)` if `k => v` is in `m`. + /// + /// Otherwise returns `None`. + /// + @Experimental + pub def get(k: k, m: DelayMap[k, v]): Option[v] with Order[k] = + let DMap(t) = m; + match RedBlackTree.get(k, t) { + case None => None + case Some(x) => Some(force x) + } + + /// + /// Returns `v` if `k => v` is in `m`. + /// + /// Otherwise, returns `d`. + /// + @Experimental + pub def getWithDefault(k: k, d: v, m: DelayMap[k, v]): v with Order[k] = + Option.getWithDefault(d, get(k, m)) + + /// + /// Returns the number of mappings `k => v` in `m` that satisfy the predicate `f`. + /// + /// Purity reflective: Runs in parallel when given a pure function `f`. + /// + @Experimental @ParallelWhenPure + pub def count(f: (k, v) -> Bool \ ef, m: DelayMap[k, v]): Int32 \ ef = + def c() = foldLeftWithKey((b, k, v) -> if (f(k, v)) b + 1 else b, 0, m); + match purityOf2(f) { + case Purity2.Pure(g) => + if (useParallelEvaluation(m)) + let h = (k, v) -> g(k, force v); + let DMap(t) = m; + RedBlackTree.parCount(h, t) + else + c() + case Purity2.Impure(_) => c() + } + + /// + /// Returns `true` if and only if `m` contains the key `k`. + /// + @Experimental + pub def memberOf(k: k, m: DelayMap[k, v]): Bool with Order[k] = + let DMap(t) = m; + RedBlackTree.memberOf(k, t) + + /// + /// Optionally finds `k => v` where `k` is the smallest key according to the `Order` instance of `k`. + /// + /// Returns `None` if `m` is empty. + /// + @Experimental + pub def minimumKey(m: DelayMap[k, v]): Option[(k, v)] = + let DMap(t) = m; + match RedBlackTree.minimumKey(t) { + case None => None + case Some((k, v)) => Some((k, force v)) + } + + /// + /// Optionally finds `k => v` where `k` is the smallest key according to the given comparator `cmp`. + /// + /// Returns `None` if `m` is empty. + /// + /// Purity reflective: Runs in parallel when given a pure function `cmp`. + /// + @Experimental @ParallelWhenPure + pub def minimumKeyBy(cmp: (k, k) -> Comparison \ ef, m: DelayMap[k, v]): Option[(k, v)] \ ef = + def min() = reduceLeftWithKey((kl, vl, kr, vr) -> if (cmp(kl, kr) == Comparison.LessThan) (kl, vl) else (kr, vr), m); + match purityOf2(cmp) { + case Purity2.Pure(g) => + if (useParallelEvaluation(m)) + let h = (kl, _, kr, _) -> g(kl, kr); + let DMap(t) = m; + let res = RedBlackTree.parMinimumBy(h, t); + match res { + case None => None + case Some((k, v)) => Some((k, force v)) + } + else + min() + case Purity2.Impure(_) => min() + } + /// + /// Optionally finds `k => v` where `v` is the smallest value. + /// + /// Returns `None` if `m` is empty. + /// + @Experimental @Parallel + pub def minimumValue(m: DelayMap[k, v]): Option[(k, v)] with Order[v] = + minimumValueBy((x, y) -> x <=> y, m) + + /// + /// Optionally finds `k => v` where `k` is the smallest value according to the given comparator `cmp`. + /// + /// Returns `None` if `m` is empty. + /// + /// Purity reflective: Runs in parallel when given a pure function `cmp`. + /// + @Experimental @ParallelWhenPure + pub def minimumValueBy(cmp: (v, v) -> Comparison \ ef, m: DelayMap[k, v]): Option[(k, v)] \ ef = + def min() = reduceLeftWithKey((kl, vl, kr, vr) -> if (cmp(vl, vr) == Comparison.LessThan) (kl, vl) else (kr, vr), m); + match purityOf2(cmp) { + case Purity2.Pure(g) => + if (useParallelEvaluation(m)) + let h = (_, vl, _, vr) -> g(force vl, force vr); + let DMap(t) = m; + let res = RedBlackTree.parMinimumBy(h, t); + match res { + case None => None + case Some((k, v)) => Some((k, force v)) + } + else + min() + case Purity2.Impure(_) => min() + } + + /// + /// Optionally finds `k => v` where `k` is the largest key according to the `Order` instance of `k`. + /// + /// Returns `None` if `m` is empty. + /// + @Experimental + pub def maximumKey(m: DelayMap[k, v]): Option[(k, v)] = + let DMap(t) = m; + match RedBlackTree.maximumKey(t) { + case None => None + case Some((k, v)) => Some((k, force v)) + } + + /// + /// Optionally finds `k => v` where `k` is the largest key according to the given comparator `cmp`. + /// + /// Returns `None` if `m` is empty. + /// + /// Purity reflective: Runs in parallel when given a pure function `cmp`. + /// + @Experimental @ParallelWhenPure + pub def maximumKeyBy(cmp: (k, k) -> Comparison \ ef, m: DelayMap[k, v]): Option[(k, v)] \ ef = + def max() = reduceLeftWithKey((kl, vl, kr, vr) -> if (cmp(kl, kr) == Comparison.GreaterThan) (kl, vl) else (kr, vr), m); + match purityOf2(cmp) { + case Purity2.Pure(g) => + if (useParallelEvaluation(m)) + let h = (kl, _, kr, _) -> g(kl, kr); + let DMap(t) = m; + let res = RedBlackTree.parMaximumBy(h, t); + match res { + case None => None + case Some((k, v)) => Some((k, force v)) + } + else + max() + case Purity2.Impure(_) => max() + } + + /// + /// Optionally finds `k => v` where `v` is the largest value. + /// + /// Returns `None` if `m` is empty. + /// + @Experimental @Parallel + pub def maximumValue(m: DelayMap[k, v]): Option[(k, v)] with Order[v] = + maximumValueBy((x, y) -> x <=> y, m) + + /// + /// Optionally finds `k => v` where `k` is the largest value according to the given comparator `cmp`. + /// + /// Returns `None` if `m` is empty. + /// + /// Purity reflective: Runs in parallel when given a pure function `cmp`. + /// + @Experimental @ParallelWhenPure + pub def maximumValueBy(cmp: (v, v) -> Comparison \ ef, m: DelayMap[k, v]): Option[(k, v)] \ ef = + def max() = reduceLeftWithKey((kl, vl, kr, vr) -> if (cmp(vl, vr) == Comparison.GreaterThan) (kl, vl) else (kr, vr), m); + match purityOf2(cmp) { + case Purity2.Pure(g) => + if (useParallelEvaluation(m)) + let h = (_, vl, _, vr) -> g(force vl, force vr); + let DMap(t) = m; + let res = RedBlackTree.parMaximumBy(h, t); + match res { + case None => None + case Some((k, v)) => Some((k, force v)) + } + else + max() + case Purity2.Impure(_) => max() + } + + /// + /// Returns the keys of `m`. + /// + @Experimental + pub def keysOf(m: DelayMap[k, v]): Set[k] with Order[k] = + foldLeftWithKey((acc, k, _) -> Set.insert(k, acc), Set.empty(), m) + + /// + /// Returns the values of `m`. + /// + @Experimental + pub def valuesOf(m: DelayMap[k, v]): List[v] = + foldRight((v, acc) -> v :: acc, Nil, m) + + /// + /// Removes the mapping `k` from the map `m`. + /// + @Experimental + pub def remove(k: k, m: DelayMap[k, v]): DelayMap[k, v] with Order[k] = + let DMap(t) = m; + DMap(RedBlackTree.remove(k, t)) + + /// + /// Updates `m` with `k => f(v, v1)` if `k => v1` is in `m`. + /// + /// Otherwise, updates `m` with `k => v`. + /// + @Experimental @LazyWhenPure + pub def insertWith(f: (v, v) -> v \ ef, k: k, v: v, m: DelayMap[k, v]): DelayMap[k, v] \ ef with Order[k] = + insertWithKey((_, v1, v2) -> f(v1, v2), k, v, m) + + /// + /// Updates `m` with `k => f(k, v, v1)` if `k => v1` is in `m`. + /// + /// Otherwise, updates `m` with `k => v`. + /// + @Experimental @LazyWhenPure + pub def insertWithKey(f: (k, v, v) -> v \ ef, k: k, v: v, m: DelayMap[k, v]): DelayMap[k, v] \ ef with Order[k] = + match purityOf3(f) { + case Purity3.Pure(g) => insertWithKeyL(g, k, v, m) + case Purity3.Impure(g) => insertWithKeyE(g, k, v, m) + } + + /// + /// Helper function for `insertWithKey`. Applies `f` lazily. + /// + @Lazy + def insertWithKeyL(f: (k, v, v) -> v, k: k, v: v, m: DelayMap[k, v]): DelayMap[k, v] with Order[k] = + let DMap(t) = m; + let f1 = (k1, v1, v2) -> lazy f(k1, force v1, force v2); + DMap(RedBlackTree.insertWith(f1, k, lazy v, t)) + + /// + /// Helper function for `insertWithKey`. Applies `f` eagerly. + /// + def insertWithKeyE(f: (k, v, v) -> v \ ef, k: k, v: v, m: DelayMap[k, v]): DelayMap[k, v] \ ef with Order[k] = + let DMap(t) = m; + let f1 = (k1, v1, v2) -> { + let x = f(k1, force v1, force v2); + lazy x + }; + DMap(RedBlackTree.insertWith(f1, k, lazy v, t)) + + /// + /// Returns a map with mappings `k => f(v)` for every `k => v` in `m`. + /// + /// Purity reflective: + /// - Runs in parallel when given a pure function `f`. + /// - Applies `f` lazily if `f` is pure. + /// + @Experimental @ParallelWhenPure @LazyWhenPure + pub def map(f: v1 -> v2 \ ef, m: DelayMap[k, v1]): DelayMap[k, v2] \ ef = + mapWithKey((_, v) -> f(v), m) + + /// + /// Returns a map with mappings `k => f(k, v)` for every `k => v` in `m`. + /// + /// Purity reflective: + /// - Runs in parallel when given a pure function `f`. + /// - Applies `f` lazily if `f` is pure. + /// + @Experimental @ParallelWhenPure @LazyWhenPure + pub def mapWithKey(f: (k, v1) -> v2 \ ef, m: DelayMap[k, v1]): DelayMap[k, v2] \ ef = + match purityOf2(f) { + case Purity2.Pure(g) => mapWithKeyL(g, m) + case Purity2.Impure(g) => mapWithKeyE(g, m) + } + + /// + /// Helper function for `mapWithKey`. Applies `f` lazily. + /// + /// Purity reflective: Runs in parallel when given a pure function `f`. + /// + @ParallelWhenPure @Lazy + def mapWithKeyL(f: (k, v1) -> v2, m: DelayMap[k, v1]): DelayMap[k, v2] = + let DMap(t) = m; + let g = (k, v) -> lazy f(k, force v); + DMap(RedBlackTree.mapWithKey(g, t)) + + /// + /// Helper function for `mapWithKey`. Applies `f` eagerly. + /// + def mapWithKeyE(f: (k, v1) -> v2 \ ef, m: DelayMap[k, v1]): DelayMap[k, v2] \ ef = + let g = (k, v) -> { + let x1 = f(k, force v); + lazy x1 + }; + let _ = parallelForce(m); + let DMap(t) = m; + DMap(RedBlackTree.mapWithKey(g, t)) + + /// + /// Forces `m` in parallel if it is big, otherwise returns `m`. + /// + @Parallel + def parallelForce(m: DelayMap[k, v]): Unit = + if (useParallelEvaluation(m)) + forceAll(m) + else + () + + /// + /// Forces **all values** in `m`. + /// + @Experimental @Parallel + pub def forceAll(m: DelayMap[k, v]): Unit = + use RedBlackTree.Node; + def seqLoop(tt) = match tt { + case Node(_, a, _, v, b) => + let _ = seqLoop(a); + let _ = force v; + seqLoop(b) + case _ => () + }; + def parLoop(n, tt) = { + if (n <= 1) + seqLoop(tt) + else + match tt { + case Node(_, a, _, v, b) => + par ( + _ <- parLoop((n - 2) / 2, a); // We divide the rest of the threads as follows: + _ <- parLoop((n - 2) / 2, b); // We spawn two new threads leaving us with n - 2 + _ <- force v // that we distribute over the two spanned threads. + ) yield () + case _ => () + } + }; + let DMap(t) = m; + if (useParallelEvaluation(m)) + parLoop(threads() - 1, t) + else + seqLoop(t) + + /// + /// Returns a map of all mappings `k => v` in `m` where `v` satisfies the predicate `f`. + /// + @Experimental + pub def filter(f: v -> Bool \ ef, m: DelayMap[k, v]): DelayMap[k, v] \ ef with Order[k] = + filterWithKey((_, v) -> f(v), m) + + /// + /// Returns a map of all mappings `k => v` in `m` where `(k, v)` satisfies the predicate `f`. + /// + @Experimental + pub def filterWithKey(f: (k, v) -> Bool \ ef, m: DelayMap[k, v]): DelayMap[k, v] \ ef with Order[k] = + foldLeftWithKey((acc, k, v) -> if (f(k, v)) insert(k, v, acc) else acc, empty(), m) + + /// + /// Returns the left-biased union of `m1` and `m2`. + /// + /// That is, key collisions are resolved by taking the mapping from `m1`. + /// + @Experimental @Lazy + pub def union(m1: DelayMap[k, v], m2: DelayMap[k, v]): DelayMap[k, v] with Order[k] = + unionWithKey((_, v1, _) -> v1, m1, m2) + + /// + /// Returns the union of `m1` and `m2` where key collisions are resolved with the merge function `f`. + /// + /// Purity reflective: Applies `f` lazily if `f` is pure. + /// + @Experimental @LazyWhenPure + pub def unionWith(f: (v, v) -> v \ ef, m1: DelayMap[k, v], m2: DelayMap[k, v]): DelayMap[k, v] \ ef with Order[k] = + unionWithKey((_, v1, v2) -> f(v1, v2), m1, m2) + + /// + /// Returns the union of `m1` and `m2` where key collisions are resolved with the merge function `f`, taking both the key and values. + /// + /// Purity reflective: Applies `f` lazily if `f` is pure. + /// + @Experimental @LazyWhenPure + pub def unionWithKey(f: (k, v, v) -> v \ ef, m1: DelayMap[k, v], m2: DelayMap[k, v]): DelayMap[k, v] \ ef with Order[k] = + match purityOf3(f) { + case Purity3.Pure(g) => unionWithKeyL(g, m1, m2) + case Purity3.Impure(g) => unionWithKeyE(g, m1, m2) + } + + /// + /// Helper function for `unionWithKey`. Applies `f` lazily. + /// + @Lazy + def unionWithKeyL(f: (k, v, v) -> v, m1: DelayMap[k, v], m2: DelayMap[k, v]): DelayMap[k, v] with Order[k] = + use RedBlackTree.{blackHeight, foldRight, insertWith}; + let DMap(xs) = m1; + let DMap(ys) = m2; + let f1 = (k, v1, v2) -> lazy (f(k, force v1, force v2)); + if (blackHeight(xs) < blackHeight(ys)) + DMap(foldRight((k, v, acc) -> insertWith(f1, k, v, acc), ys, xs)) + else + DMap(foldRight((k, v, acc) -> insertWith((_, v1, v2) -> f1(k, v2, v1), k, v, acc), xs, ys)) + + /// + /// Helper function for `unionWithKey`. Applies `f` eagerly. + /// + def unionWithKeyE(f: (k, v, v) -> v \ ef, m1: DelayMap[k, v], m2: DelayMap[k, v]): DelayMap[k, v] \ ef with Order[k] = + use RedBlackTree.{blackHeight, foldRight, insertWith}; + let DMap(xs) = m1; + let DMap(ys) = m2; + let f1 = (k, v1, v2) -> { + let x = f(k, force v1, force v2); + lazy x + }; + if (blackHeight(xs) < blackHeight(ys)) + let _ = parallelForce(m1); + DMap(foldRight((k, v, acc) -> insertWith(f1, k, v, acc), ys, xs)) + else + let _ = parallelForce(m2); + DMap(foldRight((k, v, acc) -> insertWith((_, v1, v2) -> f1(k, v2, v1), k, v, acc), xs, ys)) + + /// + /// Applies `f` to a start value `s` and all values in `m` going from left to right. + /// + /// That is, the result is of the form: `f(...f(f(s, v1), v2)..., vn)`. + /// + @Experimental + pub def foldLeft(f: (b, v) -> b \ ef, s: b, m: DelayMap[k, v]): b \ ef = + foldLeftWithKey((acc, _, v) -> f(acc, v), s, m) + + /// + /// Applies `f` to a start value `s` and all key-value pairs in `m` going from left to right. + /// + /// That is, the result is of the form: `f(...f(f(s, k1, v1), k2, v2)..., vn)`. + /// + @Experimental + pub def foldLeftWithKey(f: (b, k, v) -> b \ ef, s: b, m: DelayMap[k, v]): b \ ef = + let _ = parallelForce(m); + let DMap(t) = m; + let f1 = (b, k, v) -> f(b, k, force v); + RedBlackTree.foldLeft(f1, s, t) + + /// + /// Applies `f` to a start value `s` and all values in `m` going from right to left. + /// + /// That is, the result is of the form: `f(v1, ...f(vn-1, f(vn, s)))`. + /// + @Experimental + pub def foldRight(f: (v, b) -> b \ ef, s: b, m: DelayMap[k, v]): b \ ef = + foldRightWithKey((_, v, acc) -> f(v, acc), s, m) + + /// + /// Applies `f` to a start value `s` and all key-value pairs in `m` going from right to left. + /// + /// That is, the result is of the form: `f(k1, v1, ...f(kn-1, vn-1, f(kn, vn, s)))`. + /// + @Experimental + pub def foldRightWithKey(f: (k, v, b) -> b \ ef, s: b, m: DelayMap[k, v]): b \ ef = + let _ = parallelForce(m); + let DMap(t) = m; + let f1 = (k1, v1, b1) -> f(k1, force v1, b1); + RedBlackTree.foldRight(f1, s, t) + + /// + /// Applies `f` to all values in `m` going from left to right until a single value `v` is obtained. Returns `Some(v)`. + /// + /// That is, the result is of the form: `Some(f(...f(f(v1, v2), v3)..., vn))` + /// + /// Returns `None` if `m` is the empty map. + /// + @Experimental + pub def reduceLeft(f: (v, v) -> v \ ef, m: DelayMap[k, v]): Option[v] \ ef = + reduceLeftWithKey((k, v1, _, v2) -> (k, f(v1, v2)), m) |> Option.map(snd) + + /// + /// Applies `f` to all mappings in `m` going from left to right until a single mapping `(k, v)` is obtained. Returns `Some((k, v))`. + /// + /// That is, the result is of the form: `Some(f(...f(f(k1, v1, k2, v2), k3, v3)..., kn, vn))` + /// + /// Returns `None` if `m` is the empty map. + /// + @Experimental + pub def reduceLeftWithKey(f: (k, v, k, v) -> (k, v) \ ef, m: DelayMap[k, v]): Option[(k, v)] \ ef = + let _ = parallelForce(m); + let DMap(t) = m; + let f1 = (k1, v1, k2, v2) -> { + let (k, v) = f(k1, force v1, k2, force v2); + (k, lazy v) + }; + match RedBlackTree.reduceLeft(f1, t) { + case Some((k, v)) => Some((k, force v)) + case None => None + } + + /// + /// Applies `f` to all values in `m` going from right to left until a single value `v` is obtained. Returns `Some(v)`. + /// + /// That is, the result is of the form: `Some(f(v1, ...f(vn-2, f(vn-1, vn))...))` + /// + /// Returns `None` if `m` is the empty DelayMap. + /// + @Experimental + pub def reduceRight(f: (v, v) -> v \ ef, m: DelayMap[k, v]): Option[v] \ ef = + reduceRightWithKey((k, v1, _, v2) -> (k, f(v1, v2)), m) |> Option.map(snd) + + /// + /// Applies `f` to all mappings in `m` going from right to left until a single mapping `(k, v)` is obtained. Returns `Some((k, v))`. + /// + /// That is, the result is of the form: `Some(f(k1, v1, ...f(kn-2, vn-2, f(kn-1, vn-1, kn, vn))...))` + /// + /// Returns `None` if `m` is the empty DelayMap. + /// + @Experimental + pub def reduceRightWithKey(f: (k, v, k, v) -> (k, v) \ ef, m: DelayMap[k, v]): Option[(k, v)] \ ef = + let _ = parallelForce(m); + let DMap(t) = m; + let f1 = (k1, v1, k2, v2) -> { + let (k, v) = f(k1, force v1, k2, force v2); + (k, lazy v) + }; + match RedBlackTree.reduceRight(f1, t) { + case Some((k, v)) => Some((k, force v)) + case None => None + } + + /// + /// Updates `m` with `k => f(v)` if `k => v` is in `m`. Otherwise, returns `m`. + /// + /// Purity reflective: Applies `f` lazily if `f` is pure. + /// + @Experimental @LazyWhenPure + pub def adjust(f: v -> v \ ef, k: k, m: DelayMap[k, v]): DelayMap[k, v] \ ef with Order[k] = + adjustWithKey((_, v1) -> f(v1), k, m) + + /// + /// Updates `m` with `k => f(k, v)` if `k => v` is in `m`. Otherwise, returns `m`. + /// + /// Purity reflective: Applies `f` lazily if `f` is pure. + /// + @Experimental @LazyWhenPure + pub def adjustWithKey(f: (k, v) -> v \ ef, k: k, m: DelayMap[k, v]): DelayMap[k, v] \ ef with Order[k] = + updateWithKey((k1, v) -> Some(f(k1, v)), k, m) + + /// + /// Updates `m` with `k => v1` if `k => v` is in `m` and `f(v) = Some(v1)`. Otherwise, returns `m`. + /// + /// Purity reflective: Applies `f` lazily if `f` is pure. + /// + @Experimental @LazyWhenPure + pub def update(f: v -> Option[v] \ ef, k: k, m: DelayMap[k, v]): DelayMap[k, v] \ ef with Order[k] = + updateWithKey((_, v1) -> f(v1), k, m) + + /// + /// Updates `m` with `k => v1` if `k => v` is in `m` and `f(k, v) = Some(v1)`. Otherwise, returns `m`. + /// + /// Purity reflective: Applies `f` lazily if `f` is pure. + /// + @Experimental @LazyWhenPure + pub def updateWithKey(f: (k, v) -> Option[v] \ ef, k: k, m: DelayMap[k, v]): DelayMap[k, v] \ ef with Order[k] = + match purityOf2(f) { + case Purity2.Pure(g) => updateWithKeyL(g, k, m) + case Purity2.Impure(g) => updateWithKeyE(g, k, m) + } + + /// + /// Helper function for `updateWithKey`. Does not force the `v`. + /// + @Lazy + def updateWithKeyL(f: (k, v) -> Option[v], k: k, m: DelayMap[k, v]): DelayMap[k, v] with Order[k] = + let DMap(t) = m; + let f1 = (k1, v1) -> { + let res = lazy match f(k1, force v1) { + case Some(v2) => v2 + case None => force v1 + }; + Some(res) + }; + DMap(RedBlackTree.updateWith(f1, k, t)) + + /// + /// Helper function for `updateWithKey`. Forces `v`. + /// + def updateWithKeyE(f: (k, v) -> Option[v] \ ef, k: k, m: DelayMap[k, v]): DelayMap[k, v] \ ef with Order[k] = + let DMap(t) = m; + let f1 = (k1, v1) -> { + let res = f(k1, force v1); + match res { + case Some(v2) => Some(lazy v2) + case None => None + } + }; + DMap(RedBlackTree.updateWith(f1, k, t)) + + /// + /// Returns the map `m` as a list of key-value pairs. + /// + @Experimental + pub def toList(m: DelayMap[k, v]): List[(k, v)] = + foldRightWithKey((k, v, acc) -> (k, v) :: acc, Nil, m) + + /// + /// Returns `m` as a Map, i.e. every value is forced. + /// + @Experimental @Parallel + pub def toMap(m: DelayMap[k, v]): Map[k, v] = + let _ = parallelForce(m); + let DMap(t) = m; + Map.Map(RedBlackTree.mapWithKey((_, v) -> force v, t)) + + /// + /// Returns the map `m` as a set of key-value pairs. + /// + @Experimental + pub def toSet(m: DelayMap[k, v]): Set[(k, v)] with Order[k], Order[v] = + foldLeftWithKey((acc, k, v) -> Set.insert((k, v), acc), Set.empty(), m) + + /// + /// Returns an iterator over all key-value pairs in `m`. + /// + @Experimental + pub def iterator(rc: Region[r], m: DelayMap[a, b]): Iterator[(a, b), r, r] \ r = + let DMap(t) = m; + RedBlackTree.iterator(rc, t) |> Iterator.map(match (k, v) -> (k, force v)) + + /// + /// Applies `f` to every `(key, value)` of `m`. + /// + @Experimental + pub def forEach(f: (k, v) -> Unit \ ef, m: DelayMap[k, v]): Unit \ ef = + let _ = parallelForce(m); + let DMap(t) = m; + let f1 = (k, v) -> f(k, force v); + RedBlackTree.forEach(f1, t) + + /// + /// Applies `f` to tuple `(index, key, value)` formed of the keys and values of + /// DelayMap `m` and the index of the traversal. + /// + @Experimental + pub def forEachWithIndex(f: (Int32, k, v) -> Unit \ ef, m: DelayMap[k, v]): Unit \ ef = region rc { + let ix = Ref.fresh(rc, 0); + let f1 = (k, v) -> { let i = Ref.get(ix); f(i, k, v); Ref.put(i + 1, ix) }; + forEach(f1, m) + } + + /// + /// Returns the sum of all values in `m`. + /// + @Experimental @Parallel + pub def sumKeys(m: DelayMap[Int32, v]): Int32 = + sumWith((k, _) -> k, m) + + /// + /// Returns the sum of all values in `m`. + /// + @Experimental @Parallel + pub def sumValues(m: DelayMap[k, Int32]): Int32 = + sumWith((_, v) -> v, m) + + /// + /// Returns the sum of all key-value pairs `k => v` in `m` + /// according to the function `f`. + /// + /// Purity reflective: Runs in parallel when given a pure function `f`. + /// + @Experimental @ParallelWhenPure + pub def sumWith(f: (k, v) -> Int32 \ ef, m: DelayMap[k, v]): Int32 \ ef = + let DMap(t) = m; + def sw() = { + let _ = parallelForce(m); + RedBlackTree.sumWith((k, v) -> f(k, force v), t) + }; + match purityOf2(f) { + case Purity2.Pure(g) => + if (useParallelEvaluation(m)) + let h = (k, v) -> g(k, force v); + RedBlackTree.parSumWith(h, t) + else + sw() + case Purity2.Impure(_) => sw() + } + + /// + /// Returns the concatenation of the string representation of each key `k` + /// in `m` with `sep` inserted between each element. + /// + @Experimental + pub def joinKeys(sep: String, m: DelayMap[k, v]): String with ToString[k] = + let DMap(t) = m; + RedBlackTree.joinKeys(sep, t) + + /// + /// Returns the concatenation of the string representation of each value `v` + /// in `m` with `sep` inserted between each element. + /// + @Experimental + pub def joinValues(sep: String, m: DelayMap[k, v]): String with ToString[v] = + joinWith((_, v) -> ToString.toString(v), sep, m) + + /// + /// Returns the concatenation of the string representation of each key-value pair + /// `k => v` in `m` according to `f` with `sep` inserted between each element. + /// + @Experimental + pub def joinWith(f: (k, v) -> String \ ef, sep: String, m: DelayMap[k, v]): String \ ef = + let _ = parallelForce(m); + let DMap(t) = m; + RedBlackTree.joinWith((k, v) -> f(k, force v), sep, t) + +} diff --git a/test/TestDelayList.flix b/test/TestDelayList.flix new file mode 100644 index 0000000..433dce0 --- /dev/null +++ b/test/TestDelayList.flix @@ -0,0 +1,3120 @@ +mod TestDelayList { + + use Assert.{assertEq, assertNeq, assertTrue, assertFalse} + use Extras.DelayList + use Extras.DelayList.{ENil, ECons, LCons, LList} + use Math.Shuffle + + def toDelayList(l: List[a]): DelayList[a] = match l { + case Nil => DelayList.ENil + case x :: xs => DelayList.LCons(x, lazy toDelayList(xs)) + } + + ///////////////////////////////////////////////////////////////////////////// + // Eq // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def eq01(): Unit \ Assert = + assertEq(expected = (ENil: DelayList[Unit]), (ENil: DelayList[Unit])) + + @Test + def eq02(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), ECons(1, ENil)) + + @Test + def eq03(): Unit \ Assert = + assertEq(expected = LCons(1, lazy ENil), LCons(1, lazy ENil)) + + @Test + def eq04(): Unit \ Assert = + assertEq(expected = LList(lazy ECons(1, ENil)), LList(lazy ECons(1, ENil))) + + @Test + def eq05(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), LCons(1, lazy ENil)) + + @Test + def eq06(): Unit \ Assert = + assertEq(expected = LCons(1, lazy ENil), ECons(1, ENil)) + + @Test + def eq07(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), LList(lazy ECons(1, ENil))) + + @Test + def eq08(): Unit \ Assert = + assertEq(expected = LList(lazy ECons(1, ENil)), ECons(1, ENil)) + + @Test + def eq09(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), LList(lazy LCons(1, lazy ENil))) + + @Test + def eq10(): Unit \ Assert = + assertEq(expected = LList(lazy LCons(1, lazy ENil)), ECons(1, ENil)) + + @Test + def eq11(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(2, ECons(3, ENil))), ECons(1, ECons(2, ECons(3, ENil)))) + + @Test + def eq12(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(2, ECons(3, ENil))), LCons(1, lazy LCons(2, lazy LCons(3, lazy ENil)))) + + @Test + def eq13(): Unit \ Assert = + assertEq(expected = LCons(1, lazy LCons(2, lazy LCons(3, lazy ENil))), ECons(1, ECons(2, ECons(3, ENil)))) + + @Test + def eq14(): Unit \ Assert = + assertEq(expected = ECons(1, LCons(2, lazy ECons(3, ENil))), LCons(1, lazy LCons(2, lazy LCons(3, lazy ENil)))) + + @Test + def eq15(): Unit \ Assert = + assertEq(expected = LCons(1, lazy ECons(2, LCons(3, lazy ENil))), ECons(1, ECons(2, ECons(3, ENil)))) + + @Test + def eq16(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(2, ECons(3, ENil))), LCons(1, lazy LCons(2, lazy LCons(3, lazy ENil)))) + + @Test + def eq17(): Unit \ Assert = + assertEq(expected = LList(lazy ECons(1, ECons(2, ECons(3, ENil)))), LList(lazy LCons(1, lazy LCons(2, lazy LCons(3, lazy ENil))))) + + @Test + def eq18(): Unit \ Assert = + assertEq(expected = LList(lazy ECons(1, ECons(2, ECons(3, ENil)))), LList(lazy LCons(1, lazy LCons(2, lazy LCons(3, lazy ENil))))) + + @Test + def eq19(): Unit \ Assert = + assertNeq(unexpected = ECons(0, ENil), ECons(1, ENil)) + + @Test + def eq20(): Unit \ Assert = + assertNeq(unexpected = ECons(0, ENil), LCons(1, lazy ENil)) + + @Test + def eq21(): Unit \ Assert = + assertNeq(unexpected = LCons(0, lazy ENil), ECons(1, ENil)) + + @Test + def eq22(): Unit \ Assert = + assertNeq(unexpected = LCons(0, lazy ENil), LCons(1, lazy ENil)) + + @Test + def eq23(): Unit \ Assert = + assertNeq(unexpected = LList(lazy ECons(0, ENil)), LCons(1, lazy ENil)) + + @Test + def eq24(): Unit \ Assert = + assertNeq(unexpected = LCons(0, lazy ENil), LList(lazy ECons(1, ENil))) + + @Test + def eq25(): Unit \ Assert = + assertNeq(unexpected = ECons(0, ENil), ECons(0, ECons(0, ENil))) + + @Test + def eq26(): Unit \ Assert = + assertNeq(unexpected = ECons(0, ENil), ECons(0, ECons(1, ENil))) + + @Test + def eq27(): Unit \ Assert = + assertNeq(unexpected = ECons(0, ENil), ENil) + + @Test + def eq28(): Unit \ Assert = + assertNeq(unexpected = ENil, ECons(0, ENil)) + + @Test + def eq29(): Unit \ Assert = + assertNeq(unexpected = LCons(0, lazy ENil), ENil) + + @Test + def eq30(): Unit \ Assert = + assertNeq(unexpected = ENil, LCons(0, lazy ENil)) + + + ///////////////////////////////////////////////////////////////////////////// + // empty // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def empty01(): Unit \ Assert = + assertEq(expected = Nil, (DelayList.empty(): DelayList[Int32]) |> DelayList.toList) + + + ///////////////////////////////////////////////////////////////////////////// + // isEmpty // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def isEmpty01(): Unit \ Assert = + assertEq(expected = true, (DelayList.empty(): DelayList[Int32]) |> DelayList.isEmpty) + + @Test + def isEmpty02(): Unit \ Assert = + assertEq(expected = false, DelayList.range(0, 1000) |> DelayList.isEmpty) + + ///////////////////////////////////////////////////////////////////////////// + // nonEmpty // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def nonEmpty01(): Unit \ Assert = + assertEq(expected = false, (DelayList.empty(): DelayList[Int32]) |> DelayList.nonEmpty) + + @Test + def nonEmpty02(): Unit \ Assert = + assertEq(expected = true, DelayList.range(0, 1000) |> DelayList.nonEmpty) + + + ///////////////////////////////////////////////////////////////////////////// + // range // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def range01(): Unit \ Assert = + assertEq(expected = true, DelayList.range(0, 0) |> DelayList.isEmpty) + + @Test + def range02(): Unit \ Assert = + assertEq(expected = true, DelayList.range(100, 100) |> DelayList.isEmpty) + + @Test + def range03(): Unit \ Assert = + assertEq(expected = true, DelayList.range(1, 0) |> DelayList.isEmpty) + + @Test + def range04(): Unit \ Assert = + assertEq(expected = false, DelayList.range(0, 100) |> DelayList.isEmpty) + + @Test + def range05(): Unit \ Assert = + assertEq(expected = List.range(0, 100), DelayList.range(0, 100) |> DelayList.toList) + + @Test + def range06(): Unit \ Assert = + assertEq(expected = false, DelayList.range(-100, 100) |> DelayList.isEmpty) + + @Test + def range07(): Unit \ Assert = + assertEq(expected = List.range(-100, 100), DelayList.range(-100, 100) |> DelayList.toList) + + + ///////////////////////////////////////////////////////////////////////////// + // head // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def head01(): Unit \ Assert = + assertEq(expected = None, (DelayList.empty(): DelayList[Int32]) |> DelayList.head) + + @Test + def head02(): Unit \ Assert = + assertEq(expected = Some(0), DelayList.range(0, 1000) |> DelayList.head) + + @Test + def head03(): Unit \ Assert = + let l = DelayList.range(0, 1000); + assertEq(expected = Some(0), DelayList.head(l)); + assertEq(expected = Some(0), DelayList.head(l)) + + + ///////////////////////////////////////////////////////////////////////////// + // tail // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def tail01(): Unit \ Assert = + assertEq(expected = None, DelayList.tail((ENil: DelayList[Unit]))) + + @Test + def tail02(): Unit \ Assert = + assertEq(expected = None, DelayList.tail((LList(lazy ENil): DelayList[Unit]))) + + @Test + def tail03(): Unit \ Assert = + assertEq(expected = Some(ENil), DelayList.range(0, 1) |> DelayList.tail) + + @Test + def tail04(): Unit \ Assert = + assertEq(expected = Some(ENil), LCons(1, lazy ENil) |> DelayList.tail) + + @Test + def tail05(): Unit \ Assert = + assertEq(expected = Some(ENil), LList(lazy ECons(1, LList(lazy ENil))) |> DelayList.tail) + + @Test + def tail06(): Unit \ Assert = + assertEq(expected = Some(ENil), ECons(1, LList(lazy ENil)) |> DelayList.tail) + + @Test + def tail07(): Unit \ Assert = + assertEq(expected = Some(ENil), LCons(1, lazy LList(lazy ENil)) |> DelayList.tail) + + @Test + def tail08(): Unit \ Assert = + assertEq(expected = Some(DelayList.range(2, 4)), LCons(1, lazy LCons(2, lazy LList(lazy LCons(3, lazy ENil)))) |> DelayList.tail) + + @Test + def tail09(): Unit \ Assert = + assertEq(expected = Some(DelayList.range(2, 4)), LCons(1, lazy ECons(2, LCons(3, lazy LList(lazy ENil)))) |> DelayList.tail) + + @Test + def tail10(): Unit \ Assert = + assertEq(expected = Some(DelayList.range(2, 4)), LCons(1, lazy ECons(2, LList(lazy LCons(3, lazy LList(lazy ENil))))) |> DelayList.tail) + + @Test + def tail11(): Unit \ Assert = + assertEq(expected = Some(DelayList.range(2, 4)), LList(lazy LCons(1, lazy LList(lazy ECons(2, ECons(3, LList(lazy ENil)))))) |> DelayList.tail) + + @Test + def tail12(): Unit \ Assert = + assertEq(expected = Some(DelayList.range(1, 1000)), DelayList.range(0, 1000) |> DelayList.tail) + + + ///////////////////////////////////////////////////////////////////////////// + // init // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def init01(): Unit \ Assert = + assertEq(expected = None, DelayList.init((ENil: DelayList[Unit]))) + + @Test + def init02(): Unit \ Assert = + assertEq(expected = None, DelayList.init((LList(lazy ENil): DelayList[Unit]))) + + @Test + def init03(): Unit \ Assert = + assertEq(expected = Some(ENil), DelayList.range(0, 1) |> DelayList.init) + + @Test + def init04(): Unit \ Assert = + assertEq(expected = Some(ENil), LCons(1, lazy ENil) |> DelayList.init) + + @Test + def init05(): Unit \ Assert = + assertEq(expected = Some(ENil), LList(lazy ECons(1, LList(lazy ENil))) |> DelayList.init) + + @Test + def init06(): Unit \ Assert = + assertEq(expected = Some(ENil), ECons(1, LList(lazy ENil)) |> DelayList.init) + + @Test + def init07(): Unit \ Assert = + assertEq(expected = Some(ENil), LCons(1, lazy LList(lazy ENil)) |> DelayList.init) + + @Test + def init08(): Unit \ Assert = + assertEq(expected = Some(DelayList.range(1, 3)), LCons(1, lazy LCons(2, lazy LList(lazy LCons(3, lazy ENil)))) |> DelayList.init) + + @Test + def init09(): Unit \ Assert = + assertEq(expected = Some(DelayList.range(1, 3)), LCons(1, lazy ECons(2, LCons(3, lazy LList(lazy ENil)))) |> DelayList.init) + + @Test + def init10(): Unit \ Assert = + assertEq(expected = Some(DelayList.range(1, 3)), LCons(1, lazy ECons(2, LList(lazy LCons(3, lazy LList(lazy ENil))))) |> DelayList.init) + + @Test + def init11(): Unit \ Assert = + assertEq(expected = Some(DelayList.range(1, 3)), LList(lazy LCons(1, lazy LList(lazy ECons(2, ECons(3, LList(lazy ENil)))))) |> DelayList.init) + + @Test + def init12(): Unit \ Assert = + assertEq(expected = Some(DelayList.range(0, 999)), DelayList.range(0, 1000) |> DelayList.init) + + + ///////////////////////////////////////////////////////////////////////////// + // take // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def take01(): Unit \ Assert = + assertEq(expected = true, (DelayList.empty(): DelayList[Int32]) |> DelayList.take(1000) |> DelayList.isEmpty) + + @Test + def take02(): Unit \ Assert = + assertEq(expected = true, (DelayList.empty(): DelayList[Int32]) |> DelayList.take(0) |> DelayList.isEmpty) + + @Test + def take03(): Unit \ Assert = + assertEq(expected = true, (DelayList.range(0, 1000): DelayList[Int32]) |> DelayList.take(0) |> DelayList.isEmpty) + + @Test + def take04(): Unit \ Assert = + assertEq(expected = List.range(0, 500), (DelayList.range(0, 1000): DelayList[Int32]) + |> DelayList.take(500) + |> DelayList.toList) + + @Test + def take05(): Unit \ Assert = + assertEq(expected = List.range(0, 1), (DelayList.range(0, 1000): DelayList[Int32]) + |> DelayList.take(1) + |> DelayList.toList) + + + ///////////////////////////////////////////////////////////////////////////// + // length // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def length01(): Unit \ Assert = + assertEq(expected = 0, (DelayList.empty(): DelayList[Int32]) |> DelayList.length) + + @Test + def length02(): Unit \ Assert = + assertEq(expected = 100000, DelayList.range(0, 100000) |> DelayList.length) + + + ///////////////////////////////////////////////////////////////////////////// + // size // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def size01(): Unit \ Assert = + assertEq(expected = 0, (DelayList.empty(): DelayList[Int32]) |> DelayList.size) + + @Test + def size02(): Unit \ Assert = + assertEq(expected = 100000, DelayList.range(0, 100000) |> DelayList.size) + + + ///////////////////////////////////////////////////////////////////////////// + // reverse // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def reverse01(): Unit \ Assert = + assertEq(expected = Nil, DelayList.reverse((DelayList.empty(): DelayList[Unit])) |> DelayList.toList) + + @Test + def reverse02(): Unit \ Assert = + assertEq(expected = 1 :: Nil, (1 :: Nil) |> toDelayList |> DelayList.reverse |> DelayList.toList) + + @Test + def reverse03(): Unit \ Assert = + assertEq(expected = 2 :: 1 :: Nil, (1 :: 2 :: Nil) |> toDelayList |> DelayList.reverse |> DelayList.toList) + + @Test + def reverse04(): Unit \ Assert = + assertEq(expected = 1 :: 1 :: Nil, (1 :: 1 :: Nil) |> toDelayList |> DelayList.reverse |> DelayList.toList) + + @Test + def reverse05(): Unit \ Assert = + assertEq(expected = 3 :: 2 :: 1 :: Nil, (1 :: 2 :: 3 :: Nil) |> toDelayList |> DelayList.reverse |> DelayList.toList) + + @Test + def reverse06(): Unit \ Assert = + assertEq(expected = 4 :: 3 :: 2 :: 1 :: Nil, (1 :: 2 :: 3 :: 4 :: Nil) |> toDelayList |> DelayList.reverse |> DelayList.toList) + + @Test + def reverse07(): Unit \ Assert = + assertEq(expected = List.range(-100, 1000) |> List.reverse, DelayList.range(-100, 1000) |> DelayList.reverse |> DelayList.toList) + + + ///////////////////////////////////////////////////////////////////////////// + // map (pure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def mapPure01(): Unit \ Assert = + assertEq(expected = Nil, Nil |> toDelayList |> DelayList.map(x -> x + 1) |> DelayList.toList) + + @Test + def mapPure02(): Unit \ Assert = + assertEq(expected = 2 :: Nil, (1 :: Nil) |> toDelayList |> DelayList.map(x -> x + 1) |> DelayList.toList) + + @Test + def mapPure03(): Unit \ Assert = + assertEq(expected = 2 :: 3 :: Nil, (1 :: 2 :: Nil) |> toDelayList |> DelayList.map(x -> x + 1) |> DelayList.toList) + + @Test + def mapPure04(): Unit \ Assert = + assertEq(expected = 2 :: 3 :: 4 :: Nil, (1 :: 2 :: 3 :: Nil) |> toDelayList |> DelayList.map(x -> x + 1) |> DelayList.toList) + + + ///////////////////////////////////////////////////////////////////////////// + // map (impure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def mapImpure01(): Unit \ Assert + IO = + assertEq(expected = Nil, Nil |> toDelayList |> DelayList.map(x -> checked_ecast(x + 1)) |> DelayList.toList) + + @Test + def mapImpure02(): Unit \ Assert + IO = + assertEq(expected = 2 :: Nil, (1 :: Nil) |> toDelayList |> DelayList.map(x -> checked_ecast(x + 1)) |> DelayList.toList) + + @Test + def mapImpure03(): Unit \ Assert + IO = + assertEq(expected = 2 :: 3 :: Nil, (1 :: 2 :: Nil) |> toDelayList |> DelayList.map(x -> checked_ecast(x + 1)) |> DelayList.toList) + + @Test + def mapImpure04(): Unit \ Assert + IO = + assertEq(expected = 2 :: 3 :: 4 :: Nil, (1 :: 2 :: 3 :: Nil) |> toDelayList |> DelayList.map(x -> checked_ecast(x + 1)) |> DelayList.toList) + + + ///////////////////////////////////////////////////////////////////////////// + // map map // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def mapMap01(): Unit \ Assert = + assertEq(expected = 4 :: 6 :: 8 :: Nil, (1 :: 2 :: 3 :: Nil) |> + toDelayList |> + DelayList.map(x -> x + 1) |> + DelayList.map(x -> x * 2) |> + DelayList.toList) + + @Test + def mapMap02(): Unit \ Assert + IO = + assertEq(expected = 4 :: 6 :: 8 :: Nil, (1 :: 2 :: 3 :: Nil) |> + toDelayList |> + DelayList.map(x -> checked_ecast(x + 1)) |> + DelayList.map(x -> x * 2) |> + DelayList.toList) + + @Test + def mapMap03(): Unit \ Assert + IO = + assertEq(expected = 4 :: 6 :: 8 :: Nil, (1 :: 2 :: 3 :: Nil) |> + toDelayList |> + DelayList.map(x -> x + 1) |> + DelayList.map(x -> checked_ecast(x * 2)) |> + DelayList.toList) + + @Test + def mapMap04(): Unit \ Assert + IO = + assertEq(expected = 4 :: 6 :: 8 :: Nil, (1 :: 2 :: 3 :: Nil) |> + toDelayList |> + DelayList.map(x -> checked_ecast(x + 1)) |> + DelayList.map(x -> checked_ecast(x * 2)) |> + DelayList.toList) + + + ///////////////////////////////////////////////////////////////////////////// + // map map fusion // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def mapFusion01(): Unit \ Assert = region rc { + let l = Ref.fresh(rc, Nil); + discard (1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.map(x -> { Ref.put("a" :: Ref.get(l), l); x }) |> + DelayList.map(x -> { Ref.put("b" :: Ref.get(l), l); x }); + assertEq(expected = ("a" :: "a" :: "a" :: "b" :: "b" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + @Test + def mapFusion02(): Unit \ Assert + IO = region rc { + let l = Ref.fresh(rc, Nil); + discard checked_ecast((1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.map(x -> unchecked_cast({ Ref.put("a" :: Ref.get(l), l); x } as _ \ {})) |> + DelayList.map(x -> unchecked_cast({ Ref.put("b" :: Ref.get(l), l); x } as _ \ {})) |> + DelayList.toList); + assertEq(expected = ("a" :: "b" :: "a" :: "b" :: "a" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + ///////////////////////////////////////////////////////////////////////////// + // filter (pure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def filterPure01(): Unit \ Assert = + assertEq(expected = Nil, Nil |> toDelayList |> DelayList.filter(x -> x > 100) |> DelayList.toList) + + @Test + def filterPure02(): Unit \ Assert = + assertEq(expected = 1 :: 2 :: 3 :: Nil, (1 :: 2 :: 3 :: Nil) |> toDelayList |> DelayList.filter(x -> x > 0) |> DelayList.toList) + + @Test + def filterPure03(): Unit \ Assert = + assertEq(expected = 2 :: 3 :: Nil, (1 :: 2 :: 3 :: Nil) |> toDelayList |> DelayList.filter(x -> x > 1) |> DelayList.toList) + + @Test + def filterPure04(): Unit \ Assert = + assertEq(expected = 3 :: Nil, (1 :: 2 :: 3 :: Nil) |> toDelayList |> DelayList.filter(x -> x > 2) |> DelayList.toList) + + @Test + def filterPure05(): Unit \ Assert = + assertEq(expected = Nil, (1 :: 2 :: 3 :: Nil) |> toDelayList |> DelayList.filter(x -> x > 3) |> DelayList.toList) + + @Test + def filterPure06(): Unit \ Assert = + assertEq(expected = Nil, (1 :: 2 :: 3 :: Nil) |> toDelayList |> DelayList.filter(x -> x > 100) |> DelayList.toList) + + + ///////////////////////////////////////////////////////////////////////////// + // filter (impure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def filterImpure01(): Unit \ Assert + IO = + assertEq(expected = Nil, Nil |> toDelayList |> DelayList.filter(x -> checked_ecast(x > 100)) |> DelayList.toList) + + @Test + def filterImpure02(): Unit \ Assert + IO = + assertEq(expected = 1 :: 2 :: 3 :: Nil, (1 :: 2 :: 3 :: Nil) |> toDelayList |> DelayList.filter(x -> checked_ecast(x > 0)) |> DelayList.toList) + + @Test + def filterImpure03(): Unit \ Assert + IO = + assertEq(expected = 2 :: 3 :: Nil, (1 :: 2 :: 3 :: Nil) |> toDelayList |> DelayList.filter(x -> checked_ecast(x > 1)) |> DelayList.toList) + + @Test + def filterImpure04(): Unit \ Assert + IO = + assertEq(expected = 3 :: Nil, (1 :: 2 :: 3 :: Nil) |> toDelayList |> DelayList.filter(x -> checked_ecast(x > 2)) |> DelayList.toList) + + @Test + def filterImpure05(): Unit \ Assert + IO = + assertEq(expected = Nil, (1 :: 2 :: 3 :: Nil) |> toDelayList |> DelayList.filter(x -> checked_ecast(x > 3)) |> DelayList.toList) + + @Test + def filterImpure06(): Unit \ Assert + IO = + assertEq(expected = Nil, (1 :: 2 :: 3 :: Nil) |> toDelayList |> DelayList.filter(x -> checked_ecast(x > 100)) |> DelayList.toList) + + + ///////////////////////////////////////////////////////////////////////////// + // filter filter // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def filterFilter01(): Unit \ Assert = + assertEq(expected = 2 :: Nil, (1 :: 2 :: 3 :: Nil) |> + toDelayList |> + DelayList.filter(x -> x > 1) |> + DelayList.filter(x -> x < 3) |> + DelayList.toList) + + @Test + def filterFilter02(): Unit \ Assert + IO = + assertEq(expected = 2 :: Nil, (1 :: 2 :: 3 :: Nil) |> + toDelayList |> + DelayList.filter(x -> checked_ecast(x > 1)) |> + DelayList.filter(x -> x < 3) |> + DelayList.toList) + + @Test + def filterFilter03(): Unit \ Assert + IO = + assertEq(expected = 2 :: Nil, (1 :: 2 :: 3 :: Nil) |> + toDelayList |> + DelayList.filter(x -> x > 1) |> + DelayList.filter(x -> checked_ecast(x < 3)) |> + DelayList.toList) + + @Test + def filterFilter04(): Unit \ Assert + IO = + assertEq(expected = 2 :: Nil, (1 :: 2 :: 3 :: Nil) |> + toDelayList |> + DelayList.filter(x -> checked_ecast(x > 1)) |> + DelayList.filter(x -> checked_ecast(x < 3)) |> + DelayList.toList) + + + ///////////////////////////////////////////////////////////////////////////// + // filter filter fusion // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def filterFusion01(): Unit \ Assert = region rc { + let l = Ref.fresh(rc, Nil); + discard (1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.filter(_ -> { Ref.put("a" :: Ref.get(l), l); true }) |> + DelayList.filter(_ -> { Ref.put("b" :: Ref.get(l), l); true }); + assertEq(expected = ("a" :: "a" :: "a" :: "b" :: "b" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + @Test + def filterFusion02(): Unit \ Assert + IO = region rc { + let l = Ref.fresh(rc, Nil); + discard checked_ecast((1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.filter(_x -> unchecked_cast({ Ref.put("a" :: Ref.get(l), l); true } as _ \ {})) |> + DelayList.filter(_x -> unchecked_cast({ Ref.put("b" :: Ref.get(l), l); true } as _ \ {})) |> + DelayList.toList); + assertEq(expected = ("a" :: "b" :: "a" :: "b" :: "a" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + ///////////////////////////////////////////////////////////////////////////// + // map filter fusion // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def mapFilterFusion01(): Unit \ Assert = region rc { + let l = Ref.fresh(rc, Nil); + discard (1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.map( x -> { Ref.put("a" :: Ref.get(l), l); x }) |> + DelayList.filter(_ -> { Ref.put("b" :: Ref.get(l), l); true }); + assertEq(expected = ("a" :: "a" :: "a" :: "b" :: "b" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + @Test + def mapFilterFusion02(): Unit \ Assert + IO = region rc { + let l = Ref.fresh(rc, Nil); + discard checked_ecast((1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.map( x -> unchecked_cast({ Ref.put("a" :: Ref.get(l), l); x } as _ \ {})) |> + DelayList.filter(_ -> unchecked_cast({ Ref.put("b" :: Ref.get(l), l); true } as _ \ {})) |> + DelayList.toList); + assertEq(expected = ("a" :: "b" :: "a" :: "b" :: "a" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + ///////////////////////////////////////////////////////////////////////////// + // filter map fusion // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def filterThenMapFusion01(): Unit \ Assert = region rc { + let l = Ref.fresh(rc, Nil); + discard (1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.filter(_ -> { Ref.put("a" :: Ref.get(l), l); true }) |> + DelayList.map( x -> { Ref.put("b" :: Ref.get(l), l); x }); + assertEq(expected = ("a" :: "a" :: "a" :: "b" :: "b" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + @Test + def filterThenMapFusion02(): Unit \ Assert + IO = region rc { + let l = Ref.fresh(rc, Nil); + discard checked_ecast((1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.filter(_ -> unchecked_cast({ Ref.put("a" :: Ref.get(l), l); true } as _ \ {})) |> + DelayList.map( x -> unchecked_cast({ Ref.put("b" :: Ref.get(l), l); x } as _ \ {})) |> + DelayList.toList); + assertEq(expected = ("a" :: "b" :: "a" :: "b" :: "a" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + ///////////////////////////////////////////////////////////////////////////// + // foldLeft // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def foldLeft01(): Unit \ Assert = + assertEq(expected = 100, DelayList.foldLeft((i, e) -> (i - e) * (e `Int32.remainder` 2 + 1), 100, ENil)) + + @Test + def foldLeft02(): Unit \ Assert = + assertEq(expected = 100, DelayList.foldLeft((i, e) -> (i - e) * (e `Int32.remainder` 2 + 1), 100, LList(lazy ENil))) + + @Test + def foldLeft03(): Unit \ Assert = + assertEq(expected = 198, DelayList.foldLeft((i, e) -> (i - e) * (e `Int32.remainder` 2 + 1), 100, LCons(1, lazy ENil))) + + @Test + def foldLeft04(): Unit \ Assert = + assertEq(expected = 196, DelayList.foldLeft((i, e) -> (i - e) * (e `Int32.remainder` 2 + 1), 100, LList(lazy LCons(1, lazy ECons(2, LList(lazy ENil)))))) + + @Test + def foldLeft05(): Unit \ Assert = + assertEq(expected = 386, DelayList.foldLeft((i, e) -> (i - e) * (e `Int32.remainder` 2 + 1), 100, LCons(1, lazy LCons(2, lazy LList(lazy LCons(3, lazy ENil)))))) + + @Test + def foldLeft06(): Unit \ Assert = + assertEq(expected = 3 :: 2 :: 1 :: Nil, DelayList.foldLeft((acc, x) -> x :: acc, Nil, LList(lazy LCons(1, lazy LList(lazy ECons(2, ECons(3, LList(lazy ENil)))))))) + + + ///////////////////////////////////////////////////////////////////////////// + // foldRight // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def foldRight01(): Unit \ Assert = + assertEq(expected = 100, DelayList.foldRight((e, acc) -> (acc - e) * (e `Int32.remainder` 2 + 1), 100, ENil)) + + @Test + def foldRight02(): Unit \ Assert = + assertEq(expected = 100, DelayList.foldRight((e, acc) -> (acc - e) * (e `Int32.remainder` 2 + 1), 100, LList(lazy ENil))) + + @Test + def foldRight03(): Unit \ Assert = + assertEq(expected = 198, DelayList.foldRight((e, acc) -> (acc - e) * (e `Int32.remainder` 2 + 1), 100, LCons(1, lazy LList(lazy ENil)))) + + @Test + def foldRight04(): Unit \ Assert = + assertEq(expected = 194, DelayList.foldRight((e, acc) -> (acc - e) * (e `Int32.remainder` 2 + 1), 100, ECons(1, LCons(2, lazy ENil)))) + + @Test + def foldRight05(): Unit \ Assert = + assertEq(expected = 382, DelayList.foldRight((e, acc) -> (acc - e) * (e `Int32.remainder` 2 + 1), 100, LCons(1, lazy ECons(2, LCons(3, lazy LList(lazy ENil)))))) + + @Test + def foldRight06(): Unit \ Assert = + assertEq(expected = 1 :: 2 :: 3 :: Nil, DelayList.foldRight((x, acc) -> x :: acc, Nil, LList(lazy LCons(1, lazy LList(lazy ECons(2, ECons(3, LList(lazy ENil)))))))) + + ///////////////////////////////////////////////////////////////////////////// + // foldMap // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def foldMap01(): Unit \ Assert = + assertEq(expected = 0, DelayList.foldMap(x -> 2 * x, ENil)) + + @Test + def foldMap02(): Unit \ Assert = + assertEq(expected = 0, DelayList.foldMap(x -> 2 * x, LList(lazy ENil))) + + @Test + def foldMap03(): Unit \ Assert = + assertEq(expected = 2, DelayList.foldMap(x -> 2 * x, LCons(1, lazy LList(lazy ENil)))) + + @Test + def foldMap04(): Unit \ Assert = + assertEq(expected = 6, DelayList.foldMap(x -> 2 * x, ECons(1, LCons(2, lazy ENil)))) + + @Test + def foldMap05(): Unit \ Assert = + assertEq(expected = 12, DelayList.foldMap(x -> 2 * x, LCons(1, lazy ECons(2, LCons(3, lazy LList(lazy ENil)))))) + + @Test + def foldMap06(): Unit \ Assert = + assertEq(expected = "123", DelayList.foldMap(Int32.toString, LCons(1, lazy ECons(2, LCons(3, lazy LList(lazy ENil)))))) + + ///////////////////////////////////////////////////////////////////////////// + // forEach // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def forEach01(): Unit \ Assert = region rc { + let l = ENil; + let sb = StringBuilder.empty(rc); + let fn = x -> if (x > 0) StringBuilder.append('T', sb) else StringBuilder.append('F', sb); + DelayList.forEach(fn, l); + assertEq(expected = "", StringBuilder.toString(sb)) + } + + @Test + def forEach02(): Unit \ Assert = region rc { + let l = LList(lazy ENil); + let sb = StringBuilder.empty(rc); + let fn = x -> if (x > 0) StringBuilder.append('T', sb) else StringBuilder.append('F', sb); + DelayList.forEach(fn, l); + assertEq(expected = "", StringBuilder.toString(sb)) + } + + @Test + def forEach03(): Unit \ Assert = region rc { + let l = LCons(1, lazy LList(lazy ENil)); + let sb = StringBuilder.empty(rc); + let fn = x -> if (x > 0) StringBuilder.append('T', sb) else StringBuilder.append('F', sb); + DelayList.forEach(fn, l); + assertEq(expected = "T", StringBuilder.toString(sb)) + } + + @Test + def forEach04(): Unit \ Assert = region rc { + let l = LCons(-1, lazy LList(lazy ENil)); + let sb = StringBuilder.empty(rc); + let fn = x -> if (x > 0) StringBuilder.append('T', sb) else StringBuilder.append('F', sb); + DelayList.forEach(fn, l); + assertEq(expected = "F", StringBuilder.toString(sb)) + } + + @Test + def forEach05(): Unit \ Assert = region rc { + let l = ECons(1, LCons(-1, lazy ENil)); + let sb = StringBuilder.empty(rc); + let fn = x -> if (x > 0) StringBuilder.append('T', sb) else StringBuilder.append('F', sb); + DelayList.forEach(fn, l); + assertEq(expected = "TF", StringBuilder.toString(sb)) + } + + ///////////////////////////////////////////////////////////////////////////// + // forEachWithIndex // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def forEachWithIndex01(): Unit \ Assert = region rc { + let l = ENil; + let sb = StringBuilder.empty(rc); + let fn = (i, _) -> if (i > 0) StringBuilder.append('T', sb) else StringBuilder.append('F', sb); + DelayList.forEachWithIndex(fn, l); + assertEq(expected = "", StringBuilder.toString(sb)) + } + + @Test + def forEachWithIndex02(): Unit \ Assert = region rc { + let l = LList(lazy ENil); + let sb = StringBuilder.empty(rc); + let fn = (i, _) -> if (i > 0) StringBuilder.append('T', sb) else StringBuilder.append('F', sb); + DelayList.forEachWithIndex(fn, l); + assertEq(expected = "", StringBuilder.toString(sb)) + } + + @Test + def forEachWithIndex03(): Unit \ Assert = region rc { + let l = LCons(1, lazy LList(lazy ENil)); + let sb = StringBuilder.empty(rc); + let fn = (i, _) -> if (i > 0) StringBuilder.append('T', sb) else StringBuilder.append('F', sb); + DelayList.forEachWithIndex(fn, l); + assertEq(expected = "F", StringBuilder.toString(sb)) + } + + @Test + def forEachWithIndex04(): Unit \ Assert = region rc { + let l = LCons(-1, lazy LList(lazy ENil)); + let sb = StringBuilder.empty(rc); + let fn = (i, _) -> if (i > 0) StringBuilder.append('T', sb) else StringBuilder.append('F', sb); + DelayList.forEachWithIndex(fn, l); + assertEq(expected = "F", StringBuilder.toString(sb)) + } + + @Test + def forEachWithIndex05(): Unit \ Assert = region rc { + let l = ECons(1, LCons(-1, lazy ENil)); + let sb = StringBuilder.empty(rc); + let fn = (i, _) -> if (i > 0) StringBuilder.append('T', sb) else StringBuilder.append('F', sb); + DelayList.forEachWithIndex(fn, l); + assertEq(expected = "FT", StringBuilder.toString(sb)) + } + + ///////////////////////////////////////////////////////////////////////////// + // toArray // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def toArray01(): Unit \ Assert = region rc { + assertEq(expected = true, DelayList.toArray(rc, (ENil: DelayList[Unit]))`Array.sameElements` Array#{} @ rc) + } + + @Test + def toArray02(): Unit \ Assert = region rc { + assertEq(expected = true, DelayList.toArray(rc, (LList(lazy ENil): DelayList[Unit]))`Array.sameElements` Array#{} @ rc) + } + + @Test + def toArray03(): Unit \ Assert = region rc { + assertEq(expected = true, DelayList.toArray(rc, DelayList.range(-100, 1000))`Array.sameElements` Array.range(rc, -100, 1000)) + } + + @Test + def toArray04(): Unit \ Assert = region rc { + assertEq(expected = true, DelayList.toArray(rc, LCons(1, lazy ENil))`Array.sameElements` Array#{1} @ rc) + } + + @Test + def toArray05(): Unit \ Assert = region rc { + assertEq(expected = true, DelayList.toArray(rc, LList(lazy LCons(1, lazy LList(lazy ECons(2, ECons(3, LList(lazy ENil)))))))`Array.sameElements` Array#{1, 2, 3} @ rc) + } + + ///////////////////////////////////////////////////////////////////////////// + // toVector // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def toVector01(): Unit \ Assert = + assertEq(expected = true, ((DelayList.toVector(ENil)) : Vector[Int32]) `Vector.equals` Vector.empty()) + + @Test + def toVector02(): Unit \ Assert = + assertEq(expected = true, DelayList.toVector(LCons(0, lazy ENil)) `Vector.equals` Vector.singleton(0)) + + @Test + def toVector03(): Unit \ Assert = + assertEq(expected = true, DelayList.toVector(DelayList.range(1, 4)) `Vector.equals` Vector.range(1, 4)) + + ///////////////////////////////////////////////////////////////////////////// + // toList // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def toList01(): Unit \ Assert = + assertEq(expected = Nil, (DelayList.toList(ENil): List[Unit])) + + @Test + def toList02(): Unit \ Assert = + assertEq(expected = Nil, (DelayList.toList(LList(lazy ENil)): List[Unit])) + + @Test + def toList03(): Unit \ Assert = + assertEq(expected = List.range(-1000, 1000), DelayList.range(-1000, 1000) |> DelayList.toList) + + @Test + def toList04(): Unit \ Assert = + assertEq(expected = List.range(-1000, 0), DelayList.range(-1000, 1000000) |> DelayList.take(1000) |> DelayList.toList) + + @Test + def toList05(): Unit \ Assert = + assertEq(expected = 1 :: 2 :: 3 :: Nil, (1 :: 2 :: 3 :: Nil) |> toDelayList |> DelayList.toList) + + @Test + def toList06(): Unit \ Assert = + assertEq(expected = 1 :: 2 :: 3 :: Nil, DelayList.toList(LList(lazy LCons(1, lazy LList(lazy ECons(2, ECons(3, LList(lazy ENil)))))))) + + + ///////////////////////////////////////////////////////////////////////////// + // toMutDeque // + ///////////////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////////////////// + // toMap // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def toMap01(): Unit \ Assert = assertEq(expected = Map#{}, DelayList.toMap((ENil: DelayList[(Unit, Unit)]))) + + @Test + def toMap02(): Unit \ Assert = assertEq(expected = Map#{}, DelayList.toMap((LList(lazy ENil): DelayList[(Unit, Unit)]))) + + @Test + def toMap03(): Unit \ Assert = assertEq(expected = Map#{1 => true}, DelayList.toMap(ECons((1, true), ENil))) + + @Test + def toMap04(): Unit \ Assert = assertEq(expected = Map#{1 => true, 2 => false}, DelayList.toMap(LList(lazy LCons((1, true), lazy LList(lazy LCons((2, false), lazy ENil)))))) + + @Test + def toMap05(): Unit \ Assert = assertEq(expected = Map#{1 => false}, DelayList.toMap(ECons((1, true), ECons((1, false), ENil)))) + + + ///////////////////////////////////////////////////////////////////////////// + // toSet // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def toSet01(): Unit \ Assert = + assertEq(expected = Set.empty(), (DelayList.toSet(ENil): Set[Unit])) + + @Test + def toSet02(): Unit \ Assert = + assertEq(expected = Set.empty(), (DelayList.toSet(LList(lazy ENil)): Set[Unit])) + + @Test + def toSet03(): Unit \ Assert = + assertEq(expected = Set.range(-1000, 1000), DelayList.range(-1000, 1000) |> DelayList.toSet) + + @Test + def toSet04(): Unit \ Assert = + assertEq(expected = Set.range(-1000, 0), DelayList.range(-1000, 1000000) |> DelayList.take(1000) |> DelayList.toSet) + + @Test + def toSet05(): Unit \ Assert = + assertEq(expected = Set#{1, 2, 3}, DelayList.toSet(LList(lazy LCons(1, lazy LList(lazy ECons(2, LList(lazy ECons(3, ENil)))))))) + + + ///////////////////////////////////////////////////////////////////////////// + // append // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def append01(): Unit \ Assert = + assertEq(expected = ENil, DelayList.append((ENil: DelayList[Unit]), (ENil: DelayList[Unit]))) + + @Test + def append02(): Unit \ Assert = + assertEq(expected = ENil, DelayList.append((LList(lazy ENil): DelayList[Unit]), (ENil: DelayList[Unit]))) + + @Test + def append03(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), DelayList.append(ECons(1, ENil), ENil)) + + @Test + def append04(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), DelayList.append(ENil, LCons(1, lazy ENil))) + + @Test + def append05(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(2, ECons(3, ECons(4, ENil)))), DelayList.append(ECons(1, ECons(2, ECons(3, ENil))), ECons(4, LList(lazy ENil)))) + + @Test + def append06(): Unit \ Assert = + assertEq(expected = ECons(4, ECons(1, ECons(2, ECons(3, ENil)))), DelayList.append(ECons(4, ENil), ECons(1, LCons(2, lazy LList(lazy LCons(3, lazy ENil)))))) + + + ///////////////////////////////////////////////////////////////////////////// + // count // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def count01(): Unit \ Assert = + assertEq(expected = 0, DelayList.count(x -> x > 3, ENil)) + + @Test + def count02(): Unit \ Assert = + assertEq(expected = 0, DelayList.count(x -> x > 3, LList(lazy LCons(1, lazy LList(lazy LCons(1, lazy LList(lazy LCons(1, lazy ENil)))))))) + + @Test + def count03(): Unit \ Assert = + assertEq(expected = 1, DelayList.count(x -> x > 3, ECons(4, ENil))) + + @Test + def count04(): Unit \ Assert = + assertEq(expected = 1000, DelayList.count(_ -> true, DelayList.range(1000, 2000))) + + @Test + def count05(): Unit \ Assert = + assertEq(expected = 0, DelayList.count(_ -> false, DelayList.range(1000, 2000))) + + @Test + def count06(): Unit \ Assert = + assertEq(expected = 0, DelayList.count(x -> x > 3, ECons(1, ECons(2, ENil)))) + + @Test + def count07(): Unit \ Assert = + assertEq(expected = 1, DelayList.count(x -> x > 3, ECons(1, ECons(8, ENil)))) + + @Test + def count08(): Unit \ Assert = + assertEq(expected = 1, DelayList.count(x -> x > 3, ECons(8, ECons(1, ENil)))) + + + ///////////////////////////////////////////////////////////////////////////// + // drop // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def drop01(): Unit \ Assert = + assertEq(expected = ENil, DelayList.drop(-1, (ENil: DelayList[Unit]))) + + @Test + def drop02(): Unit \ Assert = + assertEq(expected = ENil, DelayList.drop(0, (ENil: DelayList[Unit]))) + + @Test + def drop03(): Unit \ Assert = + assertEq(expected = ENil, DelayList.drop(1, (ENil: DelayList[Unit]))) + + @Test + def drop04(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), DelayList.drop(-1, ECons(1, ENil))) + + @Test + def drop05(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), DelayList.drop(0, ECons(1, ENil))) + + @Test + def drop06(): Unit \ Assert = + assertEq(expected = ENil, DelayList.drop(1, ECons(1, ENil))) + + @Test + def drop07(): Unit \ Assert = + assertEq(expected = ENil, DelayList.drop(1, LList(lazy ECons(1, LList(lazy ENil))))) + + @Test + def drop08(): Unit \ Assert = + assertEq(expected = ENil, DelayList.drop(2, ECons(1, ENil))) + + @Test + def drop09(): Unit \ Assert = + assertEq(expected = DelayList.range(500, 1000), DelayList.range(0, 1000) |> DelayList.drop(500)) + + + ///////////////////////////////////////////////////////////////////////////// + // flatten // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def flatten01(): Unit \ Assert = + assertEq(expected = ENil, DelayList.flatten((ENil: DelayList[DelayList[Unit]]))) + + @Test + def flatten02(): Unit \ Assert = + assertEq(expected = ENil, (DelayList.flatten(ECons(ENil, ENil)): DelayList[Unit])) + + @Test + def flatten03(): Unit \ Assert = + assertEq(expected = ENil, (DelayList.flatten(ECons(ENil, ECons(ENil, ENil))): DelayList[Unit])) + + @Test + def flatten04(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), DelayList.flatten(ECons(LCons(1, lazy ENil), ENil))) + + @Test + def flatten05(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), DelayList.flatten(ECons(LList(lazy ECons(1, LList(lazy ENil))), ENil))) + + @Test + def flatten06(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(2, ENil)), DelayList.flatten(ECons((ECons(1, ECons(2, ENil))), ENil))) + + @Test + def flatten07(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(2, ENil)), DelayList.flatten(ECons(ENil, ECons(LList(lazy LCons(1, lazy LList(lazy LCons(2, lazy ENil)))), ENil)))) + + @Test + def flatten08(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(2, ECons(1, ECons(2, ENil)))), DelayList.flatten(ECons(ECons(1, LCons(2, lazy ENil)), ECons((ECons(1, ECons(2, ENil))), ENil)))) + + @Test + def flatten09(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(2, ECons(3, ECons(4, ENil)))), DelayList.flatten(ECons((ECons(1, ECons(2, ENil))), ECons(ENil, ECons(ENil, ECons(LList(lazy LCons(3, lazy LCons(4, lazy ENil))), ENil)))))) + + + ///////////////////////////////////////////////////////////////////////////// + // exists // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def exists01(): Unit \ Assert = + assertFalse(DelayList.exists(i -> i > 3, ENil)) + + @Test + def exists02(): Unit \ Assert = + assertFalse((1 :: Nil) |> toDelayList |> DelayList.exists(i -> i > 3)) + + @Test + def exists03(): Unit \ Assert = + assertTrue((5 :: Nil) |> toDelayList |> DelayList.exists(i -> i > 3)) + + @Test + def exists04(): Unit \ Assert = + assertFalse((1 :: 2 :: Nil) |> toDelayList |> DelayList.exists(i -> i > 3)) + + @Test + def exists05(): Unit \ Assert = + assertTrue((1 :: 6 :: Nil) |> toDelayList |> DelayList.exists(i -> i > 3)) + + @Test + def exists06(): Unit \ Assert = + assertTrue((6 :: 1 :: Nil) |> toDelayList |> DelayList.exists(i -> i > 3)) + + @Test + def exists07(): Unit \ Assert = + assertTrue((16 :: 6 :: Nil) |> toDelayList |> DelayList.exists(i -> i > 3)) + + @Test + def exists08(): Unit \ Assert = + assertFalse((1 :: -9 :: 3 :: Nil) |> toDelayList |> DelayList.exists(i -> i > 3)) + + @Test + def exists09(): Unit \ Assert = + assertTrue((1 :: 9 :: 3 :: Nil) |> toDelayList |> DelayList.exists(i -> i > 3)) + + + ///////////////////////////////////////////////////////////////////////////// + // forAll // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def forAll01(): Unit \ Assert = + assertTrue(DelayList.forAll(i -> i > 3, ENil)) + + @Test + def forAll02(): Unit \ Assert = + assertFalse((1 :: Nil) |> toDelayList |> DelayList.forAll(i -> i > 3)) + + @Test + def forAll03(): Unit \ Assert = + assertTrue((5 :: Nil) |> toDelayList |> DelayList.forAll(i -> i > 3)) + + @Test + def forAll04(): Unit \ Assert = + assertFalse((1 :: 2 :: Nil) |> toDelayList |> DelayList.forAll(i -> i > 3)) + + @Test + def forAll05(): Unit \ Assert = + assertFalse((1 :: 6 :: Nil) |> toDelayList |> DelayList.forAll(i -> i > 3)) + + @Test + def forAll06(): Unit \ Assert = + assertFalse((6 :: 1 :: Nil) |> toDelayList |> DelayList.forAll(i -> i > 3)) + + @Test + def forAll07(): Unit \ Assert = + assertTrue((16 :: 6 :: Nil) |> toDelayList |> DelayList.forAll(i -> i > 3)) + + @Test + def forAll08(): Unit \ Assert = + assertFalse((1 :: -9 :: 3 :: Nil) |> toDelayList |> DelayList.forAll(i -> i > 3)) + + @Test + def forAll09(): Unit \ Assert = + assertFalse((1 :: 9 :: 3 :: Nil) |> toDelayList |> DelayList.forAll(i -> i > 3)) + + @Test + def forAll10(): Unit \ Assert = + assertTrue((11 :: 9 :: 31 :: Nil) |> toDelayList |> DelayList.forAll(i -> i > 3)) + + + ///////////////////////////////////////////////////////////////////////////// + // repeat // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def repeat01(): Unit \ Assert = + assertEq(expected = ENil, DelayList.repeat(1) |> DelayList.take(-1)) + + @Test + def repeat02(): Unit \ Assert = + assertEq(expected = ENil, DelayList.repeat(1) |> DelayList.take(0)) + + @Test + def repeat03(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), DelayList.repeat(1) |> DelayList.take(1)) + + @Test + def repeat04(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(1, ENil)), DelayList.repeat(1) |> DelayList.take(2)) + + @Test + def repeat05(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(1, ECons(1, ENil))), DelayList.repeat(1) |> DelayList.take(3)) + + @Test + def repeat07(): Unit \ Assert = + assertEq(expected = ECons(3, ECons(3, ECons(3, ENil))), DelayList.repeat(3) |> DelayList.take(3)) + + @Test + def repeat08(): Unit \ Assert = + assertEq(expected = ECons("a", ECons("a", ECons("a", ENil))), DelayList.repeat("a") |> DelayList.take(3)) + + + ///////////////////////////////////////////////////////////////////////////// + // from // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def startFrom01(): Unit \ Assert = + assertEq(expected = ENil, DelayList.startFrom(-1) |> DelayList.take(0)) + + @Test + def startFrom02(): Unit \ Assert = + assertEq(expected = ENil, DelayList.startFrom(0) |> DelayList.take(0)) + + @Test + def startFrom04(): Unit \ Assert = + assertEq(expected = ENil, DelayList.startFrom(100) |> DelayList.take(-1)) + + @Test + def startFrom05(): Unit \ Assert = + assertEq(expected = ECons(-1, ENil), DelayList.startFrom(-1) |> DelayList.take(1)) + + @Test + def startFrom06(): Unit \ Assert = + assertEq(expected = ECons(5, ENil), DelayList.startFrom(5) |> DelayList.take(1)) + + @Test + def startFrom07(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(2, ECons(3, ENil))), DelayList.startFrom(1) |> DelayList.take(3)) + + @Test + def startFrom08(): Unit \ Assert = + assertEq(expected = DelayList.range(-1000, 0), DelayList.startFrom(-1000) |> DelayList.take(1000)) + + @Test + def startFrom09(): Unit \ Assert = + assertEq(expected = DelayList.range(-1000, 1000), DelayList.startFrom(-1000) |> DelayList.take(2000)) + + @Test + def startFrom10(): Unit \ Assert = + assertEq(expected = DelayList.range(0, 2000), DelayList.startFrom(0) |> DelayList.take(2000)) + + + ///////////////////////////////////////////////////////////////////////////// + // last // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def last01(): Unit \ Assert = + assertEq(expected = None, DelayList.last((ENil: DelayList[Unit]))) + + @Test + def last02(): Unit \ Assert = + assertEq(expected = None, DelayList.last((LList(lazy ENil): DelayList[Unit]))) + + @Test + def last03(): Unit \ Assert = + assertEq(expected = Some(0), DelayList.range(0, 1) |> DelayList.last) + + @Test + def last06(): Unit \ Assert = + assertEq(expected = Some(1), ECons(1, ENil) |> DelayList.last) + + @Test + def last11(): Unit \ Assert = + assertEq(expected = Some(3), LList(lazy LCons(1, lazy LList(lazy ECons(2, ECons(3, LList(lazy ENil)))))) |> DelayList.last) + + @Test + def last12(): Unit \ Assert = + assertEq(expected = Some(999), DelayList.range(0, 1000) |> DelayList.last) + + + ///////////////////////////////////////////////////////////////////////////// + // iterator // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def toIter01(): Unit \ Assert = region rc { + assertEq(expected = Nil, DelayList.iterator(rc, (ENil: DelayList[Unit])) |> Iterator.toList) + } + + @Test + def toIter02(): Unit \ Assert = region rc { + assertEq(expected = Nil, DelayList.iterator(rc, (LList(lazy ENil): DelayList[Unit])) |> Iterator.toList) + } + + @Test + def toIter06(): Unit \ Assert = region rc { + assertEq(expected = 1 :: 2 :: 3 :: Nil, DelayList.iterator(rc, LList(lazy LCons(1, lazy LList(lazy ECons(2, ECons(3, LList(lazy ENil))))))) |> Iterator.toList) + } + + @Test + def toIter09(): Unit \ Assert = region rc { + assertEq(expected = List.range(-100, 100), DelayList.range(-100, 100) |> DelayList.iterator(rc) |> Iterator.toList) + } + + + ///////////////////////////////////////////////////////////////////////////// + // zip // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def zip01(): Unit \ Assert = + assertEq(expected = ENil, DelayList.zip((ENil: DelayList[Int32]), (ENil: DelayList[String]))) + + @Test + def zip02(): Unit \ Assert = + assertEq(expected = ENil, DelayList.zip((LList(lazy ENil): DelayList[Int32]), (ENil: DelayList[String]))) + + @Test + def zip03(): Unit \ Assert = + assertEq(expected = ENil, DelayList.zip((ENil: DelayList[Int32]), (LList(lazy ENil): DelayList[String]))) + + @Test + def zip04(): Unit \ Assert = + assertEq(expected = ENil, DelayList.zip((LList(lazy ENil): DelayList[Int32]), (LList(lazy ENil): DelayList[String]))) + + @Test + def zip05(): Unit \ Assert = + assertEq(expected = ENil, DelayList.zip(ECons(1, ECons(2, ENil)), (ENil: DelayList[String]))) + + @Test + def zip06(): Unit \ Assert = + assertEq(expected = ENil, DelayList.zip((ENil: DelayList[String]), ECons(1, ECons(2, ENil)))) + + @Test + def zip07(): Unit \ Assert = + assertEq(expected = ECons(("a", 1), ECons(("b", 2), ENil)), DelayList.zip(LCons("a", lazy ECons("b", LList(lazy ECons("c", ENil)))), LList(lazy LCons(1, lazy LList(lazy LCons(2, lazy ENil)))))) + + @Test + def zip08(): Unit \ Assert = + assertEq(expected = ECons((1, "a"), ECons((2, "b"), ECons((3, "c"), ENil))), DelayList.zip(LCons(1, lazy LCons(2, lazy LList(lazy LCons(3, lazy ENil)))), LCons("a", lazy ECons("b", LList(lazy ECons("c", ENil)))))) + + @Test + def zip09(): Unit \ Assert = + assertEq(expected = ECons((1, 1), ECons((2, 2), ECons((3, 3), ENil))), DelayList.zip(DelayList.range(1, 10), DelayList.range(1, 10)) |> DelayList.take(3)) + + + ///////////////////////////////////////////////////////////////////////////// + // zipWith (pure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def zipWithPure01(): Unit \ Assert = + assertEq(expected = ENil, (ENil: DelayList[Int32]) |> DelayList.zipWith((x, y) -> x + y, (ENil: DelayList[Int32]))) + + @Test + def zipWithPure02(): Unit \ Assert = + assertEq(expected = ENil, LList(lazy ((ENil: DelayList[Int32]))) |> DelayList.zipWith((x, y) -> x + y, (ENil: DelayList[Int32]))) + + @Test + def zipWithPure03(): Unit \ Assert = + assertEq(expected = ENil, ECons(1, ECons(2, ENil)) |> DelayList.zipWith((x, y) -> x + y, (ENil: DelayList[Int32]))) + + @Test + def zipWithPure04(): Unit \ Assert = + assertEq(expected = ENil, (ENil: DelayList[Int32]) |> DelayList.zipWith((x, y) -> x + y, ECons(1, ECons(2, ENil)))) + + @Test + def zipWithPure05(): Unit \ Assert = + assertEq(expected = ECons(2, ECons(4, ENil)), ECons(1, ECons(2, ENil)) |> DelayList.zipWith((x, y) -> x + y, ECons(1, ECons(2, ENil)))) + + @Test + def zipWithPure06(): Unit \ Assert = + assertEq(expected = ECons(2, ENil), ECons(1, ENil) |> DelayList.zipWith((x, y) -> x + y, ECons(1, ECons(2, ENil)))) + + @Test + def zipWithPure07(): Unit \ Assert = + assertEq(expected = ECons(2, ECons(4, ENil)), LList(lazy LCons(1, lazy LList(lazy LCons(2, lazy ENil)))) |> DelayList.zipWith((x, y) -> x + y, LList(lazy LCons(1, lazy LList(lazy LCons(2, lazy ENil)))))) + + + ///////////////////////////////////////////////////////////////////////////// + // zipWith (impure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def zipWithImpure01(): Unit \ Assert = + assertEq(expected = ENil, (ENil: DelayList[Int32]) |> DelayList.zipWith((x, y) -> x + y, (ENil: DelayList[Int32]))) + + @Test + def zipWithImpure02(): Unit \ Assert = + assertEq(expected = ENil, LList(lazy ((ENil: DelayList[Int32]))) |> DelayList.zipWith((x, y) -> x + y, (ENil: DelayList[Int32]))) + + @Test + def zipWithImpure03(): Unit \ Assert = + assertEq(expected = ENil, ECons(1, ECons(2, ENil)) |> DelayList.zipWith((x, y) -> x + y, (ENil: DelayList[Int32]))) + + @Test + def zipWithImpure04(): Unit \ Assert = + assertEq(expected = ENil, (ENil: DelayList[Int32]) |> DelayList.zipWith((x, y) -> x + y, ECons(1, ECons(2, ENil)))) + + @Test + def zipWithImpure05(): Unit \ Assert = + assertEq(expected = ECons(2, ECons(4, ENil)), ECons(1, ECons(2, ENil)) |> DelayList.zipWith((x, y) -> x + y, ECons(1, ECons(2, ENil)))) + + @Test + def zipWithImpure06(): Unit \ Assert = + assertEq(expected = ECons(2, ENil), ECons(1, ENil) |> DelayList.zipWith((x, y) -> x + y, ECons(1, ECons(2, ENil)))) + + @Test + def zipWithImpure07(): Unit \ Assert = + assertEq(expected = ECons(2, ECons(4, ENil)), LList(lazy LCons(1, lazy LList(lazy LCons(2, lazy ENil)))) |> DelayList.zipWith((x, y) -> x + y, LList(lazy LCons(1, lazy LList(lazy LCons(2, lazy ENil)))))) + + + ///////////////////////////////////////////////////////////////////////////// + // zipWith zipWith // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def zipWithZipWith01(): Unit \ Assert = + assertEq(expected = ECons(3, ECons(6, ECons(9, ENil))), ECons(1, ECons(2, ECons(3, ENil))) |> + DelayList.zipWith((x, y) -> x + y, ECons(1, ECons(2, ECons(3, ENil)))) |> + DelayList.zipWith((x, y) -> x + y, ECons(1, ECons(2, ECons(3, ENil))))) + + @Test + def zipWithZipWith02(): Unit \ Assert = + assertEq(expected = ECons(3, ECons(6, ECons(9, ENil))), ECons(1, ECons(2, ECons(3, ENil))) |> + DelayList.zipWith((x, y) -> x + y, ECons(1, ECons(2, ECons(3, ENil)))) |> + DelayList.zipWith((x, y) -> x + y, ECons(1, ECons(2, ECons(3, ENil))))) + + @Test + def zipWithZipWith03(): Unit \ Assert = + assertEq(expected = ECons(3, ECons(6, ECons(9, ENil))), ECons(1, ECons(2, ECons(3, ENil))) |> + DelayList.zipWith((x, y) -> x + y, ECons(1, ECons(2, ECons(3, ENil)))) |> + DelayList.zipWith((x, y) -> x + y, ECons(1, ECons(2, ECons(3, ENil))))) + + @Test + def zipWithZipWith04(): Unit \ Assert = + assertEq(expected = ECons(3, ECons(6, ECons(9, ENil))), ECons(1, ECons(2, ECons(3, ENil))) |> + DelayList.zipWith((x, y) -> x + y, ECons(1, ECons(2, ECons(3, ENil)))) |> + DelayList.zipWith((x, y) -> x + y, ECons(1, ECons(2, ECons(3, ENil))))) + + + ///////////////////////////////////////////////////////////////////////////// + // zipWith zipWith fusion // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def zipWithFusion01(): Unit \ Assert = region rc { + let l = Ref.fresh(rc, Nil); + discard (1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.zipWith((x, y) -> { Ref.put("a" :: Ref.get(l), l); (x, y) }, ECons(1, ECons(2, ECons(3, ENil)))) |> + DelayList.zipWith((x, y) -> { Ref.put("b" :: Ref.get(l), l); (x, y) }, ECons(1, ECons(2, ECons(3, ENil)))); + assertEq(expected = "a" :: "a" :: "a" :: "b" :: "b" :: "b" :: Nil, List.reverse(Ref.get(l))) + } + + @Test + def zipWithFusion02(): Unit \ Assert + IO = region rc { + let l = Ref.fresh(rc, Nil); + discard checked_ecast((1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.zipWith((x, y) -> unchecked_cast({ Ref.put("a" :: Ref.get(l), l); (x, y) } as _ \ {}), ECons(1, ECons(2, ECons(3, ENil)))) |> + DelayList.zipWith((x, y) -> unchecked_cast({ Ref.put("b" :: Ref.get(l), l); (x, y) } as _ \ {}), ECons(1, ECons(2, ECons(3, ENil)))) |> + DelayList.toList); + assertEq(expected = ("a" :: "b" :: "a" :: "b" :: "a" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + ///////////////////////////////////////////////////////////////////////////// + // zipWithIndex // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def zipWithIndex01(): Unit \ Assert = + assertEq(expected = (ENil: DelayList[(Int32, Unit)]), DelayList.zipWithIndex((ENil: DelayList[Unit]))) + + @Test + def zipWithIndex02(): Unit \ Assert = + assertEq(expected = ECons((0, 1), ENil), DelayList.zipWithIndex(ECons(1, ENil))) + + @Test + def zipWithIndex03(): Unit \ Assert = + assertEq(expected = LCons((0, 1), lazy ENil), DelayList.zipWithIndex(LCons(1, lazy ENil))) + + @Test + def zipWithIndex04(): Unit \ Assert = + assertEq(expected = LList(lazy ECons((0, 1), ENil)), DelayList.zipWithIndex(LList(lazy ECons(1, ENil)))) + + @Test + def zipWithIndex05(): Unit \ Assert = + let l = DelayList.zipWithIndex(LList(lazy LList(lazy LCons(5, lazy ECons(7, ENil))))); + assertEq(expected = LList(lazy LList(lazy LCons((0, 5), lazy ECons((1, 7), ENil)))), l) + + @Test + def zipWithIndex06(): Unit \ Assert = + let l = DelayList.zipWithIndex(LList(lazy LCons(0, lazy LList(lazy + LCons(1, lazy LList(lazy LCons(2, lazy + LList(lazy LCons(3, lazy LList(lazy + LCons(4, lazy LList(lazy LCons(5, lazy + LList(lazy LCons(10, lazy LList(lazy ENil)))))))))))))))); + assertEq(expected = LList(lazy LCons((0, 0), lazy LList(lazy + LCons((1, 1), lazy LList(lazy LCons((2, 2), lazy + LList(lazy LCons((3, 3), lazy LList(lazy + LCons((4, 4), lazy LList(lazy LCons((5, 5), lazy + LList(lazy LCons((6, 10), lazy LList(lazy ENil))))))))))))))), l) + + ///////////////////////////////////////////////////////////////////////////// + // reduceLeft // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def reduceLeft01(): Unit \ Assert = + assertEq(expected = None, DelayList.reduceLeft((a, b) -> a + b, (ENil: DelayList[Int32]))) + + @Test + def reduceLeft02(): Unit \ Assert = + assertEq(expected = Some(1), DelayList.reduceLeft((a, b) -> a + b, ECons(1, ENil))) + + @Test + def reduceLeft03(): Unit \ Assert = + assertEq(expected = Some(3), DelayList.reduceLeft((a, b) -> a + b, ECons(1, ECons(2, ENil)))) + + @Test + def reduceLeft04(): Unit \ Assert = + assertEq(expected = Some(6), DelayList.reduceLeft((a, b) -> a + b, ECons(1, ECons(2, ECons(3, ENil))))) + + @Test + def reduceLeft05(): Unit \ Assert = + assertEq(expected = Some(-8), DelayList.reduceLeft((a, b) -> a - b, LList(lazy ECons(1, LCons(2, lazy ECons(3, LList(lazy LCons(4, lazy ENil)))))))) + + @Test + def reduceLeft06(): Unit \ Assert = + assertEq(expected = Some(2), DelayList.reduceLeft((a, b) -> b - a, ECons(1, ECons(2, ECons(3, ECons(4, ENil)))))) + + + ///////////////////////////////////////////////////////////////////////////// + // reduceRight // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def reduceRight01(): Unit \ Assert = + assertEq(expected = None, DelayList.reduceRight((a, b) -> a + b, (ENil: DelayList[Int32]))) + + @Test + def reduceRight02(): Unit \ Assert = + assertEq(expected = None, DelayList.reduceRight((a, b) -> a + b, (LList(lazy ENil): DelayList[Int32]))) + + @Test + def reduceRight03(): Unit \ Assert = + assertEq(expected = Some(1), DelayList.reduceRight((a, b) -> a + b, ECons(1, ENil))) + + @Test + def reduceRight04(): Unit \ Assert = + assertEq(expected = Some(3), DelayList.reduceRight((a, b) -> a + b, ECons(1, ECons(2, ENil)))) + + @Test + def reduceRight05(): Unit \ Assert = + assertEq(expected = Some(6), DelayList.reduceRight((a, b) -> a + b, ECons(1, ECons(2, ECons(3, ENil))))) + + @Test + def reduceRight06(): Unit \ Assert = + assertEq(expected = Some(-2), DelayList.reduceRight((a, b) -> b - a, ECons(1, ECons(2, ECons(3, ECons(4, ENil)))))) + + @Test + def reduceRight07(): Unit \ Assert = + assertEq(expected = Some(-2), DelayList.reduceRight((a, b) -> a - b, LList(lazy ECons(1, LCons(2, lazy ECons(3, LList(lazy LCons(4, lazy ENil)))))))) + + + ///////////////////////////////////////////////////////////////////////////// + // minimum // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def minimum01(): Unit \ Assert = + assertEq(expected = None, DelayList.minimum((ENil: DelayList[Int32]))) + + @Test + def minimum02(): Unit \ Assert = + assertEq(expected = Some(1), DelayList.minimum(ECons(1, ENil))) + + @Test + def minimum03(): Unit \ Assert = + assertEq(expected = Some(1), DelayList.minimum(ECons(3, ECons(2, ECons(1, ENil))))) + + @Test + def minimum04(): Unit \ Assert = + assertEq(expected = Some(0), DelayList.minimum(ECons(0, ECons(3, ECons(2, ECons(1, ENil)))))) + + @Test + def minimum05(): Unit \ Assert = + assertEq(expected = Some(0), DelayList.minimum(DelayList.range(0, 99))) + + + ///////////////////////////////////////////////////////////////////////////// + // minimumBy // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def minimumBy01(): Unit \ Assert = + assertEq(expected = None, DelayList.minimumBy((x, y) -> x <=> y, (ENil: DelayList[Int32]))) + + @Test + def minimumBy02(): Unit \ Assert = + assertEq(expected = Some(1), DelayList.minimumBy((x, y) -> x <=> y, ECons(1, ENil))) + + @Test + def minimumBy03(): Unit \ Assert = + assertEq(expected = Some(1), DelayList.minimumBy((x, y) -> x <=> y, ECons(3, ECons(2, ECons(1, ENil))))) + + @Test + def minimumBy04(): Unit \ Assert = + assertEq(expected = Some(0), DelayList.minimumBy((x, y) -> x <=> y, ECons(0, ECons(3, ECons(2, ECons(1, ENil)))))) + + @Test + def minimumBy05(): Unit \ Assert = + assertEq(expected = Some(0), DelayList.minimumBy((_, _) -> Comparison.LessThan, DelayList.range(0, 99))) + + + ///////////////////////////////////////////////////////////////////////////// + // maximum // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def maximum01(): Unit \ Assert = + assertEq(expected = None, DelayList.maximum((ENil: DelayList[Int32]))) + + @Test + def maximum02(): Unit \ Assert = + assertEq(expected = Some(1), DelayList.maximum(ECons(1, ENil))) + + @Test + def maximum03(): Unit \ Assert = + assertEq(expected = Some(3), DelayList.maximum(ECons(3, ECons(2, ECons(1, ENil))))) + + @Test + def maximum04(): Unit \ Assert = + assertEq(expected = Some(3), DelayList.maximum(ECons(0, ECons(3, ECons(2, ECons(1, ENil)))))) + + @Test + def maximum05(): Unit \ Assert = + assertEq(expected = Some(98), DelayList.maximum(DelayList.range(0, 99))) + + + ///////////////////////////////////////////////////////////////////////////// + // maximumBy // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def maximumBy01(): Unit \ Assert = + assertEq(expected = None, DelayList.maximumBy((x, y) -> x <=> y, (ENil: DelayList[Int32]))) + + @Test + def maximumBy02(): Unit \ Assert = + assertEq(expected = Some(1), DelayList.maximumBy((x, y) -> x <=> y, ECons(1, ENil))) + + @Test + def maximumBy03(): Unit \ Assert = + assertEq(expected = Some(3), DelayList.maximumBy((x, y) -> x <=> y, ECons(3, ECons(2, ECons(1, ENil))))) + + @Test + def maximumBy04(): Unit \ Assert = + assertEq(expected = Some(3), DelayList.maximumBy((x, y) -> x <=> y, ECons(0, ECons(3, ECons(2, ECons(1, ENil)))))) + + @Test + def maximumBy05(): Unit \ Assert = + assertEq(expected = Some(98), DelayList.maximumBy((_, _) -> Comparison.LessThan, DelayList.range(0, 99))) + + + ///////////////////////////////////////////////////////////////////////////// + // flatMap (pure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def flatMapPure01(): Unit \ Assert = + assertEq(expected = ENil, DelayList.flatMap(i -> DelayList.repeat(i) |> DelayList.take(i), (ENil: DelayList[Int32]))) + + @Test + def flatMapPure02(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), DelayList.flatMap(i -> DelayList.repeat(i) |> DelayList.take(i), ECons(1, ENil))) + + @Test + def flatMapPure03(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(2, ECons(2, ECons(3, ECons(3, ECons(3, ENil)))))), DelayList.flatMap(i -> DelayList.repeat(i) |> DelayList.take(i), ECons(1, ECons(2, ECons(3, ENil))))) + + @Test + def flatMapPure04(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(2, ECons(2, ECons(3, ECons(3, ECons(3, ENil)))))), DelayList.flatMap(i -> DelayList.repeat(i) |> DelayList.take(i), ECons(1, LList(lazy LCons(2, lazy LList(lazy ECons(3, LList(lazy ENil)))))))) + + + ///////////////////////////////////////////////////////////////////////////// + // flatMap (impure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def flatMapImpure01(): Unit \ Assert + IO = + assertEq(expected = ENil, DelayList.flatMap(i -> checked_ecast(DelayList.repeat(i) |> DelayList.take(i)), (ENil: DelayList[Int32]))) + + @Test + def flatMapImpure02(): Unit \ Assert + IO = + assertEq(expected = ECons(1, ENil), DelayList.flatMap(i -> checked_ecast(DelayList.repeat(i) |> DelayList.take(i)), ECons(1, ENil))) + + @Test + def flatMapImpure03(): Unit \ Assert + IO = + assertEq(expected = ECons(1, ECons(2, ECons(2, ECons(3, ECons(3, ECons(3, ENil)))))), DelayList.flatMap(i -> checked_ecast(DelayList.repeat(i) |> DelayList.take(i)), ECons(1, ECons(2, ECons(3, ENil))))) + + @Test + def flatMapImpure04(): Unit \ Assert + IO = + assertEq(expected = ECons(1, ECons(2, ECons(2, ECons(3, ECons(3, ECons(3, ENil)))))), DelayList.flatMap(i -> checked_ecast(DelayList.repeat(i) |> DelayList.take(i)), ECons(1, LList(lazy LCons(2, lazy LList(lazy ECons(3, LList(lazy ENil)))))))) + + + ///////////////////////////////////////////////////////////////////////////// + // flatMap flatMap // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def flatMapFlatMap01(): Unit \ Assert = + let l = ECons(1, ECons(2, ECons(3, ENil))) |> + DelayList.flatMap(i -> DelayList.repeat(i) |> DelayList.take(i)) |> + DelayList.flatMap(i -> DelayList.repeat(i) |> DelayList.take(i)); + assertEq(expected = ECons(1, + ECons(2, ECons(2, ECons(2, ECons(2, + ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ENil)))))))))))))), l) + + @Test + def flatMapFlatMap02(): Unit \ Assert + IO = + let l = ECons(1, ECons(2, ECons(3, ENil))) |> + DelayList.flatMap(i -> checked_ecast(DelayList.repeat(i) |> DelayList.take(i))) |> + DelayList.flatMap(i -> DelayList.repeat(i) |> DelayList.take(i)); + assertEq(expected = ECons(1, + ECons(2, ECons(2, ECons(2, ECons(2, + ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ENil)))))))))))))), l) + + @Test + def flatMapFlatMap03(): Unit \ Assert + IO = + let l = ECons(1, ECons(2, ECons(3, ENil))) |> + DelayList.flatMap(i -> DelayList.repeat(i) |> DelayList.take(i)) |> + DelayList.flatMap(i -> checked_ecast(DelayList.repeat(i) |> DelayList.take(i))); + assertEq(expected = ECons(1, + ECons(2, ECons(2, ECons(2, ECons(2, + ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ENil)))))))))))))), l) + + @Test + def flatMapFlatMap04(): Unit \ Assert + IO = + let l = ECons(1, ECons(2, ECons(3, ENil))) |> + DelayList.flatMap(i -> checked_ecast(DelayList.repeat(i) |> DelayList.take(i))) |> + DelayList.flatMap(i -> checked_ecast(DelayList.repeat(i) |> DelayList.take(i))); + assertEq(expected = ECons(1, + ECons(2, ECons(2, ECons(2, ECons(2, + ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ECons(3, ENil)))))))))))))), l) + + + ///////////////////////////////////////////////////////////////////////////// + // flatMap flatMap fusion // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def flatMapFusion01(): Unit \ Assert = region rc { + let l = Ref.fresh(rc, Nil); + discard (1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.flatMap(i -> { Ref.put("a" :: Ref.get(l), l); ECons(i, ENil) }) |> + DelayList.flatMap(i -> { Ref.put("b" :: Ref.get(l), l); ECons(i, ENil) }); + assertEq(expected = ("a" :: "a" :: "a" :: "b" :: "b" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + @Test + def flatMapFusion02(): Unit \ Assert + IO = region rc { + let l = Ref.fresh(rc, Nil); + discard checked_ecast((1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.flatMap(i -> unchecked_cast({ Ref.put("a" :: Ref.get(l), l); ECons(i, ENil) } as _ \ {})) |> + DelayList.flatMap(i -> unchecked_cast({ Ref.put("b" :: Ref.get(l), l); ECons(i, ENil) } as _ \ {})) |> + DelayList.toList); + assertEq(expected = ("a" :: "b" :: "a" :: "b" :: "a" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + ///////////////////////////////////////////////////////////////////////////// + // memberOf // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def memberOf01(): Unit \ Assert = + assertFalse(DelayList.memberOf(0, ENil)) + + @Test + def memberOf02(): Unit \ Assert = + assertFalse(DelayList.memberOf(0, ECons(1, ENil))) + + @Test + def memberOf03(): Unit \ Assert = + assertFalse(DelayList.memberOf(0, ECons(1, ECons(2, ECons(3, ENil))))) + + @Test + def memberOf04(): Unit \ Assert = + assertTrue(DelayList.memberOf(0, ECons(1, ECons(2, ECons(3, ECons(0, ENil)))))) + + @Test + def memberOf05(): Unit \ Assert = + assertTrue(DelayList.memberOf(0, ECons(0, ECons(1, ECons(2, ECons(3, ENil)))))) + + @Test + def memberOf06(): Unit \ Assert = + assertTrue(DelayList.memberOf(0, ECons(1, ECons(1, ECons(1, ECons(0, ENil)))))) + + @Test + def memberOf07(): Unit \ Assert = + assertTrue(DelayList.memberOf(1, ECons(1, ECons(1, ECons(1, ECons(1, ENil)))))) + + @Test + def memberOf08(): Unit \ Assert = + assertTrue(DelayList.memberOf(0, ECons(1, ECons(1, ECons(0, ECons(1, ENil)))))) + + @Test + def memberOf09(): Unit \ Assert = + assertTrue(DelayList.memberOf(-2, ECons(1, ECons(1000, ECons(-2, ECons(1, ENil)))))) + + @Test + def memberOf10(): Unit \ Assert = + assertTrue(DelayList.memberOf(0, LList(lazy LCons(1, lazy LList(lazy LCons(2, lazy LCons(3, lazy LCons(0, lazy ENil)))))))) + + + ///////////////////////////////////////////////////////////////////////////// + // replace // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def replace01(): Unit \ Assert = + assertEq(expected = ENil, DelayList.replace(src = 3, dst = 4, ENil)) + + @Test + def replace02(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), DelayList.replace(src = 3, dst = 4, ECons(1, ENil))) + + @Test + def replace03(): Unit \ Assert = + assertEq(expected = ECons(4, ENil), DelayList.replace(src = 3, dst = 4, ECons(3, ENil))) + + @Test + def replace04(): Unit \ Assert = + assertEq(expected = ECons(4, ECons(4, ECons(4, ENil))), DelayList.replace(src = 3, dst = 4, ECons(4, ECons(4, ECons(4, ENil))))) + + @Test + def replace05(): Unit \ Assert = + assertEq(expected = ECons(2, ECons(2, ECons(2, ENil))), DelayList.replace(src = 3, dst = 4, ECons(2, ECons(2, ECons(2, ENil))))) + + @Test + def replace06(): Unit \ Assert = + assertEq(expected = ECons(2, ECons(4, ECons(2, ENil))), DelayList.replace(src = 3, dst = 4, ECons(2, ECons(3, ECons(2, ENil))))) + + @Test + def replace07(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(1, ECons(1, ENil))), DelayList.replace(src = 0, dst = 1, ECons(0, ECons(0, ECons(0, ENil))))) + + @Test + def replace08(): Unit \ Assert = + assertEq(expected = ECons(4, ECons(4, ECons(4, ENil))), DelayList.replace(src = 3, dst = 4, LList(lazy ECons(3, LList(lazy LCons(3, lazy LList(lazy LCons(3, lazy LList(lazy ENil))))))))) + + + ///////////////////////////////////////////////////////////////////////////// + // findLeft // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def findLeft01(): Unit \ Assert = + assertEq(expected = None, DelayList.findLeft(i -> i > 2, (ENil: DelayList[Int32]))) + + @Test + def findLeft02(): Unit \ Assert = + assertEq(expected = None, DelayList.findLeft(i -> i > 2, ECons(1, ENil))) + + @Test + def findLeft03(): Unit \ Assert = + assertEq(expected = Some(3), DelayList.findLeft(i -> i > 2, ECons(3, ENil))) + + @Test + def findLeft04(): Unit \ Assert = + assertEq(expected = None, DelayList.findLeft(i -> i > 2, ECons(1, ECons(2, ENil)))) + + @Test + def findLeft05(): Unit \ Assert = + assertEq(expected = Some(6), DelayList.findLeft(i -> i > 2, ECons(6, ECons(-6, ENil)))) + + @Test + def findLeft06(): Unit \ Assert = + assertEq(expected = Some(7), DelayList.findLeft(i -> i > 2, ECons(7, ECons(6, ENil)))) + + @Test + def findLeft07(): Unit \ Assert = + assertEq(expected = Some(4), DelayList.findLeft(i -> i > 2, LList(lazy ECons(1, LList(lazy LCons(1, lazy LList(lazy LCons(4, lazy LList(lazy ENil))))))))) + + + ///////////////////////////////////////////////////////////////////////////// + // findRight // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def findRight01(): Unit \ Assert = + assertEq(expected = None, DelayList.findRight(i -> i > 2, (ENil: DelayList[Int32]))) + + @Test + def findRight02(): Unit \ Assert = + assertEq(expected = None, DelayList.findRight(i -> i > 2, ECons(1, ENil))) + + @Test + def findRight03(): Unit \ Assert = + assertEq(expected = Some(3), DelayList.findRight(i -> i > 2, ECons(3, ENil))) + + @Test + def findRight04(): Unit \ Assert = + assertEq(expected = None, DelayList.findRight(i -> i > 2, ECons(1, ECons(2, ENil)))) + + @Test + def findRight05(): Unit \ Assert = + assertEq(expected = Some(6), DelayList.findRight(i -> i > 2, ECons(6, ECons(-6, ENil)))) + + @Test + def findRight06(): Unit \ Assert = + assertEq(expected = Some(6), DelayList.findRight(i -> i > 2, ECons(7, ECons(6, ENil)))) + + @Test + def findRight07(): Unit \ Assert = + assertEq(expected = Some(4), DelayList.findRight(i -> i > 2, LList(lazy ECons(4, LList(lazy LCons(1, lazy LList(lazy LCons(1, lazy LList(lazy ENil))))))))) + + + ///////////////////////////////////////////////////////////////////////////// + // mapWithIndex (pure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def mapWithIndexPure01(): Unit \ Assert = + assertEq(expected = ENil, ENil |> DelayList.mapWithIndex((i, x) -> x + i)) + + @Test + def mapWithIndexPure02(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), ECons(1, ENil) |> DelayList.mapWithIndex((i, x) -> x + i)) + + @Test + def mapWithIndexPure03(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(3, ENil)), ECons(1, ECons(2, ENil)) |> DelayList.mapWithIndex((i, x) -> x + i)) + + @Test + def mapWithIndexPure04(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(3, ECons(5, ENil))), ECons(1, ECons(2, ECons(3, ENil))) |> DelayList.mapWithIndex((i, x) -> x + i)) + + @Test + def mapWithIndexPure05(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(3, ECons(5, ECons(7, ENil)))), ECons(1, ECons(2, ECons(3, ECons(4, ENil)))) |> DelayList.mapWithIndex((i, x) -> x + i)) + + @Test + def mapWithIndexPure06(): Unit \ Assert = + let l = LList(lazy LCons(1, lazy LList(lazy LCons(2, lazy LList(lazy ECons(3, LList(lazy LCons(4, lazy LList(lazy ENil))))))))) |> DelayList.mapWithIndex((i, x) -> x + i); + assertEq(expected = ECons(1, ECons(3, ECons(5, ECons(7, ENil)))), l) + + + ///////////////////////////////////////////////////////////////////////////// + // mapWithIndex (impure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def mapWithIndexImpure01(): Unit \ Assert + IO = + assertEq(expected = ENil, ENil |> DelayList.mapWithIndex((i, x) -> checked_ecast(x + i))) + + @Test + def mapWithIndexImpure02(): Unit \ Assert + IO = + assertEq(expected = ECons(1, ENil), ECons(1, ENil) |> DelayList.mapWithIndex((i, x) -> checked_ecast(x + i))) + + @Test + def mapWithIndexImpure03(): Unit \ Assert + IO = + assertEq(expected = ECons(1, ECons(3, ENil)), ECons(1, ECons(2, ENil)) |> DelayList.mapWithIndex((i, x) -> checked_ecast(x + i))) + + @Test + def mapWithIndexImpure04(): Unit \ Assert + IO = + assertEq(expected = ECons(1, ECons(3, ECons(5, ENil))), ECons(1, ECons(2, ECons(3, ENil))) |> DelayList.mapWithIndex((i, x) -> checked_ecast(x + i))) + + @Test + def mapWithIndexImpure05(): Unit \ Assert + IO = + assertEq(expected = ECons(1, ECons(3, ECons(5, ECons(7, ENil)))), ECons(1, ECons(2, ECons(3, ECons(4, ENil)))) |> DelayList.mapWithIndex((i, x) -> checked_ecast(x + i))) + + @Test + def mapWithIndexImpure06(): Unit \ Assert + IO = + let l = LList(lazy LCons(1, lazy LList(lazy LCons(2, lazy LList(lazy ECons(3, LList(lazy LCons(4, lazy LList(lazy ENil))))))))) |> DelayList.mapWithIndex((i, x) -> checked_ecast(x + i)); + assertEq(expected = ECons(1, ECons(3, ECons(5, ECons(7, ENil)))), l) + + + ///////////////////////////////////////////////////////////////////////////// + // mapWithIndex mapWithIndex // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def mapWithIndexMapWithIndex01(): Unit \ Assert = + assertEq(expected = ECons(0, ECons(3, ECons(10, ENil))), ECons(1, ECons(2, ECons(3, ENil))) |> + DelayList.mapWithIndex((i, x) -> x + i) |> + DelayList.mapWithIndex((i, x) -> x * i)) + + @Test + def mapWithIndexMapWithIndex02(): Unit \ Assert + IO = + assertEq(expected = ECons(0, ECons(3, ECons(10, ENil))), ECons(1, ECons(2, ECons(3, ENil))) |> + DelayList.mapWithIndex((i, x) -> checked_ecast(x + i)) |> + DelayList.mapWithIndex((i, x) -> x * i)) + + @Test + def mapWithIndexMapWithIndex03(): Unit \ Assert + IO = + assertEq(expected = ECons(0, ECons(3, ECons(10, ENil))), ECons(1, ECons(2, ECons(3, ENil))) |> + DelayList.mapWithIndex((i, x) -> x + i) |> + DelayList.mapWithIndex((i, x) -> checked_ecast(x * i))) + + @Test + def mapWithIndexMapWithIndex04(): Unit \ Assert + IO = + assertEq(expected = ECons(0, ECons(3, ECons(10, ENil))), ECons(1, ECons(2, ECons(3, ENil))) |> + DelayList.mapWithIndex((i, x) -> checked_ecast(x + i)) |> + DelayList.mapWithIndex((i, x) -> checked_ecast(x * i))) + + + ///////////////////////////////////////////////////////////////////////////// + // mapWithIndex mapWithIndex fusion // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def mapWithIndexFusion01(): Unit \ Assert = region rc { + let l = Ref.fresh(rc, Nil); + discard (1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.mapWithIndex((_, x) -> { Ref.put("a" :: Ref.get(l), l); x }) |> + DelayList.mapWithIndex((_, x) -> { Ref.put("b" :: Ref.get(l), l); x }) |> + DelayList.toList; + assertEq(expected = ("a" :: "a" :: "a" :: "b" :: "b" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + @Test + def mapWithIndexFusion02(): Unit \ Assert + IO = region rc { + let l = Ref.fresh(rc, Nil); + discard checked_ecast((1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.mapWithIndex((_, x) -> unchecked_cast({ Ref.put("a" :: Ref.get(l), l); x } as _ \ {})) |> + DelayList.mapWithIndex((_, x) -> unchecked_cast({ Ref.put("b" :: Ref.get(l), l); x } as _ \ {})) |> + DelayList.toList); + assertEq(expected = ("a" :: "b" :: "a" :: "b" :: "a" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + ///////////////////////////////////////////////////////////////////////////// + // intercalate // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def intercalate01(): Unit \ Assert = + assertEq(expected = ENil, DelayList.intercalate(ECons(1, ECons(2, ENil)), ENil)) + + @Test + def intercalate02(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), DelayList.intercalate(ECons(10, ECons(11, ECons(12, ENil))), ECons(ECons(1, ENil), ENil))) + + @Test + def intercalate03(): Unit \ Assert = + let l = DelayList.intercalate( + ECons(10, ECons(11, ECons(12, ENil))), + ECons(ECons(1, ECons(2, ECons(3, ENil))), + ECons(ECons(100, ECons(101, ECons(102, ENil))), ENil))); + assertEq(expected = ECons(1, ECons(2, ECons(3, + ECons(10, ECons(11, ECons(12, + ECons(100, ECons(101, ECons(102, ENil))))))))), l) + + @Test + def intercalate04(): Unit \ Assert = + let l = DelayList.intercalate( + ECons(10, ECons(11, ECons(12, ENil))), + ECons(ECons(1, ECons(2, ECons(3, ENil))), + ECons(ECons(100, ECons(101, ECons(102, ENil))), + ECons(ECons(200, ECons(201, ECons(202, ENil))), ENil)))); + assertEq(expected = ECons(1, ECons(2, ECons(3, + ECons(10, ECons(11, ECons(12, + ECons(100, ECons(101, ECons(102, + ECons(10, ECons(11, ECons(12, + ECons(200, ECons(201, ECons(202, ENil))))))))))))))), l) + + @Test + def intercalate05(): Unit \ Assert = + let l = DelayList.intercalate( + ECons(12, ECons(11, ECons(10, ENil))), + ECons(ECons(1, ECons(2, ECons(3, ENil))), + ECons(ECons(100, ECons(101, ECons(102, ENil))), + ECons(ECons(200, ECons(201, ECons(202, ENil))), ENil)))); + assertEq(expected = ECons(1, ECons(2, ECons(3, + ECons(12, ECons(11, ECons(10, + ECons(100, ECons(101, ECons(102, + ECons(12, ECons(11, ECons(10, + ECons(200, ECons(201, ECons(202, ENil))))))))))))))), l) + + @Test + def intercalate06(): Unit \ Assert = + let l = DelayList.intercalate( + ECons(-1, ECons(-2, ECons(0, ENil))), + ECons(ECons(1, ECons(2, ECons(3, ENil))), + ECons(ECons(100, ECons(101, ECons(102, ENil))), + ECons(ECons(200, ECons(201, ECons(202, ENil))), ENil)))); + assertEq(expected = ECons(1, ECons(2, ECons(3, + ECons(-1, ECons(-2, ECons(0, + ECons(100, ECons(101, ECons(102, + ECons(-1, ECons(-2, ECons(0, + ECons(200, ECons(201, ECons(202, ENil))))))))))))))), l) + + @Test + def intercalate07(): Unit \ Assert = + let l = DelayList.intercalate( + LList(lazy LCons(10, lazy LList(lazy LCons(11, lazy LCons(12, lazy LList(lazy ENil)))))), + LList(lazy LCons(LList(lazy LCons(1, lazy LList(lazy LCons(2, lazy LList(lazy LCons(3, lazy ENil)))))), + lazy LList(lazy LCons(LList(lazy ECons(100, LList(lazy LCons(101, lazy LList(lazy LCons(102, lazy ENil)))))), + lazy LList(lazy ENil)))))); + assertEq(expected = ECons(1, ECons(2, ECons(3, + ECons(10, ECons(11, ECons(12, + ECons(100, ECons(101, ECons(102, ENil))))))))), l) + + + ///////////////////////////////////////////////////////////////////////////// + // intersperse // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def intersperse01(): Unit \ Assert = + assertEq(expected = ENil, DelayList.intersperse(-11, ENil)) + + @Test + def intersperse03(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), DelayList.intersperse(-11, ECons(1, ENil))) + + @Test + def intersperse04(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(-11, ECons(2, ECons(-11, ECons(3, ENil))))), DelayList.intersperse(-11, ECons(1, ECons(2, ECons(3, ENil))))) + + @Test + def intersperse05(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(-11, ECons(2, ECons(-11, ECons(3, ECons(-11, ECons(4, ENil))))))), DelayList.intersperse(-11, ECons(1, ECons(2, ECons(3, ECons(4, ENil)))))) + + @Test + def intersperse06(): Unit \ Assert = + let l = DelayList.intersperse(-11, LList(lazy ECons(1, LList(lazy LCons(2, lazy LList(lazy ECons(3, LList(lazy LCons(4, lazy ENil))))))))); + assertEq(expected = ECons(1, ECons(-11, ECons(2, ECons(-11, ECons(3, ECons(-11, ECons(4, ENil))))))), l) + + + ///////////////////////////////////////////////////////////////////////////// + // takeWhile (pure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def takeWhilePure01(): Unit \ Assert = + assertEq(expected = ENil, DelayList.takeWhile(i -> i > 3, ENil)) + + @Test + def takeWhilePure02(): Unit \ Assert = + assertEq(expected = ENil, DelayList.takeWhile(i -> i > 3, ECons(1, ENil))) + + @Test + def takeWhilePure03(): Unit \ Assert = + assertEq(expected = ECons(4, ENil), DelayList.takeWhile(i -> i > 3, ECons(4, ENil))) + + @Test + def takeWhilePure04(): Unit \ Assert = + assertEq(expected = ENil, DelayList.takeWhile(i -> i > 3, ECons(1, ECons(2, ENil)))) + + @Test + def takeWhilePure05(): Unit \ Assert = + assertEq(expected = ENil, DelayList.takeWhile(i -> i > 3, ECons(1, ECons(5, ENil)))) + + @Test + def takeWhilePure06(): Unit \ Assert = + assertEq(expected = ECons(5, ENil), DelayList.takeWhile(i -> i > 3, ECons(5, ECons(1, ENil)))) + + @Test + def takeWhilePure07(): Unit \ Assert = + assertEq(expected = ECons(5, ECons(8, ENil)), DelayList.takeWhile(i -> i > 3, ECons(5, ECons(8, ENil)))) + + @Test + def takeWhilePure08(): Unit \ Assert = + assertEq(expected = ECons(5, ECons(8, ENil)), DelayList.takeWhile(i -> i > 3, LList(lazy ECons(5, LList(lazy LCons(8, lazy ENil)))))) + + @Test + def takeWhilePure09(): Unit \ Assert = + let l = DelayList.takeWhile(i -> i > 3, ECons(4, ECons(6, ECons(-3, ECons(11, ECons(-5, ECons(1, ECons(2, ECons(16, ECons(7, ECons(1, ECons(7, ENil)))))))))))); + assertEq(expected = ECons(4, ECons(6, ENil)), l) + + + ///////////////////////////////////////////////////////////////////////////// + // takeWhile (impure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def takeWhileImpure01(): Unit \ Assert + IO = + assertEq(expected = ENil, DelayList.takeWhile(i -> checked_ecast(i > 3), ENil)) + + @Test + def takeWhileImpure02(): Unit \ Assert + IO = + assertEq(expected = ENil, DelayList.takeWhile(i -> checked_ecast(i > 3), ECons(1, ENil))) + + @Test + def takeWhileImpure03(): Unit \ Assert + IO = + assertEq(expected = ECons(4, ENil), DelayList.takeWhile(i -> checked_ecast(i > 3), ECons(4, ENil))) + + @Test + def takeWhileImpure04(): Unit \ Assert + IO = + assertEq(expected = ENil, DelayList.takeWhile(i -> checked_ecast(i > 3), ECons(1, ECons(2, ENil)))) + + @Test + def takeWhileImpure05(): Unit \ Assert + IO = + assertEq(expected = ENil, DelayList.takeWhile(i -> checked_ecast(i > 3), ECons(1, ECons(5, ENil)))) + + @Test + def takeWhileImpure06(): Unit \ Assert + IO = + assertEq(expected = ECons(5, ENil), DelayList.takeWhile(i -> checked_ecast(i > 3), ECons(5, ECons(1, ENil)))) + + @Test + def takeWhileImpure07(): Unit \ Assert + IO = + assertEq(expected = ECons(5, ECons(8, ENil)), DelayList.takeWhile(i -> checked_ecast(i > 3), ECons(5, ECons(8, ENil)))) + + @Test + def takeWhileImpure08(): Unit \ Assert + IO = + assertEq(expected = ECons(5, ECons(8, ENil)), DelayList.takeWhile(i -> checked_ecast(i > 3), LList(lazy ECons(5, LList(lazy LCons(8, lazy ENil)))))) + + @Test + def takeWhileImpure09(): Unit \ Assert + IO = + let l = DelayList.takeWhile(i -> checked_ecast(i > 3), ECons(4, ECons(6, ECons(-3, ECons(11, ECons(-5, ECons(1, ECons(2, ECons(16, ECons(7, ECons(1, ECons(7, ENil)))))))))))); + assertEq(expected = ECons(4, ECons(6, ENil)), l) + + + ///////////////////////////////////////////////////////////////////////////// + // takeWhile takeWhile // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def takeWhileTakeWhile01(): Unit \ Assert = + assertEq(expected = ECons(4, ENil), ECons(4, ECons(5, ECons(1, ENil))) |> + DelayList.takeWhile(i -> i > 3) |> + DelayList.takeWhile(i -> i < 5)) + + @Test + def takeWhileTakeWhile02(): Unit \ Assert + IO = + assertEq(expected = ECons(4, ENil), ECons(4, ECons(5, ECons(1, ENil))) |> + DelayList.takeWhile(i -> checked_ecast(i > 3)) |> + DelayList.takeWhile(i -> i < 5)) + + @Test + def takeWhileTakeWhile03(): Unit \ Assert + IO = + assertEq(expected = ECons(4, ENil), ECons(4, ECons(5, ECons(1, ENil))) |> + DelayList.takeWhile(i -> i > 3) |> + DelayList.takeWhile(i -> checked_ecast(i < 5))) + + @Test + def takeWhileTakeWhile04(): Unit \ Assert + IO = + assertEq(expected = ECons(4, ENil), ECons(4, ECons(5, ECons(1, ENil))) |> + DelayList.takeWhile(i -> checked_ecast(i > 3)) |> + DelayList.takeWhile(i -> checked_ecast(i < 5))) + + + ///////////////////////////////////////////////////////////////////////////// + // takeWhile takeWhile fusion // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def takeWhileFusion01(): Unit \ Assert = region rc { + let l = Ref.fresh(rc, Nil); + discard (1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.takeWhile(i -> { Ref.put("a" :: Ref.get(l), l); i < 4 }) |> + DelayList.takeWhile(i -> { Ref.put("b" :: Ref.get(l), l); i < 4 }); + assertEq(expected = ("a" :: "a" :: "a" :: "b" :: "b" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + @Test + def takeWhileFusion02(): Unit \ Assert + IO = region rc { + let l = Ref.fresh(rc, Nil); + discard checked_ecast((1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.takeWhile(i -> unchecked_cast({ Ref.put("a" :: Ref.get(l), l); i < 4 } as _ \ {})) |> + DelayList.takeWhile(i -> unchecked_cast({ Ref.put("b" :: Ref.get(l), l); i < 4 } as _ \ {})) |> + DelayList.toList); + assertEq(expected = ("a" :: "b" :: "a" :: "b" :: "a" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + @Test + def takeWhileFusion03(): Unit \ Assert + IO = region rc { + let l = Ref.fresh(rc, Nil); + discard checked_ecast((1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.takeWhile(i -> unchecked_cast({ Ref.put("a" :: Ref.get(l), l); i < 3 } as _ \ {})) |> + DelayList.takeWhile(i -> unchecked_cast({ Ref.put("b" :: Ref.get(l), l); i < 2 } as _ \ {})) |> + DelayList.toList); + assertEq(expected = ("a" :: "b" :: "a" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + @Test + def takeWhileFusion04(): Unit \ Assert + IO = region rc { + let l = Ref.fresh(rc, Nil); + discard checked_ecast((1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.takeWhile(i -> unchecked_cast({ Ref.put("a" :: Ref.get(l), l); i < 3 } as _ \ {})) |> + DelayList.takeWhile(i -> unchecked_cast({ Ref.put("b" :: Ref.get(l), l); i < 3 } as _ \ {})) |> + DelayList.toList); + assertEq(expected = ("a" :: "b" :: "a" :: "b" :: "a" :: Nil), List.reverse(Ref.get(l))) + } + + ///////////////////////////////////////////////////////////////////////////// + // dropWhile (pure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def dropWhilePure01(): Unit \ Assert = + assertEq(expected = ENil, DelayList.dropWhile(i -> i > 3, ENil)) + + @Test + def dropWhilePure02(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), DelayList.dropWhile(i -> i > 3, ECons(1, ENil))) + + @Test + def dropWhilePure03(): Unit \ Assert = + assertEq(expected = ENil, DelayList.dropWhile(i -> i > 3, ECons(4, ENil))) + + @Test + def dropWhilePure04(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(2, ENil)), DelayList.dropWhile(i -> i > 3, ECons(1, ECons(2, ENil)))) + + @Test + def dropWhilePure05(): Unit \ Assert = + assertEq(expected = ECons(1, ECons(5, ENil)), DelayList.dropWhile(i -> i > 3, ECons(1, ECons(5, ENil)))) + + @Test + def dropWhilePure06(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), DelayList.dropWhile(i -> i > 3, ECons(5, ECons(1, ENil)))) + + @Test + def dropWhilePure07(): Unit \ Assert = + assertEq(expected = ENil, DelayList.dropWhile(i -> i > 3, ECons(5, ECons(8, ENil)))) + + @Test + def dropWhilePure08(): Unit \ Assert = + let l = DelayList.dropWhile(i -> i > 3, LList(lazy ECons(5, LCons(8, lazy LList(lazy LCons(9, lazy LList(lazy ECons(10, LList(lazy LCons(1, lazy ECons(2, LList(lazy ENil)))))))))))); + assertEq(expected = ECons(1, ECons(2, ENil)), l) + + @Test + def dropWhilePure09(): Unit \ Assert = + let l = DelayList.dropWhile(i -> i > 3, ECons(4, ECons(6, ECons(-3, ECons(11, ECons(-5, ECons(1, ECons(2, ECons(16, ECons(7, ECons(1, ECons(7, ENil)))))))))))); + assertEq(expected = ECons(-3, ECons(11, ECons(-5, ECons(1, ECons(2, ECons(16, ECons(7, ECons(1, ECons(7, ENil))))))))), l) + + + ///////////////////////////////////////////////////////////////////////////// + // dropWhile (impure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def dropWhileImpure01(): Unit \ Assert + IO = + assertEq(expected = ENil, DelayList.dropWhile(i -> checked_ecast(i > 3), ENil)) + + @Test + def dropWhileImpure02(): Unit \ Assert + IO = + assertEq(expected = ECons(1, ENil), DelayList.dropWhile(i -> checked_ecast(i > 3), ECons(1, ENil))) + + @Test + def dropWhileImpure03(): Unit \ Assert + IO = + assertEq(expected = ENil, DelayList.dropWhile(i -> checked_ecast(i > 3), ECons(4, ENil))) + + @Test + def dropWhileImpure04(): Unit \ Assert + IO = + assertEq(expected = ECons(1, ECons(2, ENil)), DelayList.dropWhile(i -> checked_ecast(i > 3), ECons(1, ECons(2, ENil)))) + + @Test + def dropWhileImpure05(): Unit \ Assert + IO = + assertEq(expected = ECons(1, ECons(5, ENil)), DelayList.dropWhile(i -> checked_ecast(i > 3), ECons(1, ECons(5, ENil)))) + + @Test + def dropWhileImpure06(): Unit \ Assert + IO = + assertEq(expected = ECons(1, ENil), DelayList.dropWhile(i -> checked_ecast(i > 3), ECons(5, ECons(1, ENil)))) + + @Test + def dropWhileImpure07(): Unit \ Assert + IO = + assertEq(expected = ENil, DelayList.dropWhile(i -> checked_ecast(i > 3), ECons(5, ECons(8, ENil)))) + + @Test + def dropWhileImpure08(): Unit \ Assert + IO = + let l = DelayList.dropWhile(i -> checked_ecast(i > 3), LList(lazy ECons(5, LCons(8, lazy LList(lazy LCons(9, lazy LList(lazy ECons(10, LList(lazy LCons(1, lazy ECons(2, LList(lazy ENil)))))))))))); + assertEq(expected = ECons(1, ECons(2, ENil)), l) + + @Test + def dropWhileImpure09(): Unit \ Assert + IO = + let l = DelayList.dropWhile(i -> checked_ecast(i > 3), ECons(4, ECons(6, ECons(-3, ECons(11, ECons(-5, ECons(1, ECons(2, ECons(16, ECons(7, ECons(1, ECons(7, ENil)))))))))))); + assertEq(expected = ECons(-3, ECons(11, ECons(-5, ECons(1, ECons(2, ECons(16, ECons(7, ECons(1, ECons(7, ENil))))))))), l) + + + ///////////////////////////////////////////////////////////////////////////// + // dropWhile dropWhile // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def dropWhileDropWhile01(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), ECons(4, ECons(5, ECons(1, ENil))) |> + DelayList.dropWhile(i -> i < 5) |> + DelayList.dropWhile(i -> i > 1)) + + @Test + def dropWhileDropWhile02(): Unit \ Assert + IO = + assertEq(expected = ECons(1, ENil), ECons(4, ECons(5, ECons(1, ENil))) |> + DelayList.dropWhile(i -> checked_ecast(i < 5)) |> + DelayList.dropWhile(i -> i > 1)) + + @Test + def dropWhileDropWhile03(): Unit \ Assert + IO = + assertEq(expected = ECons(1, ENil), ECons(4, ECons(5, ECons(1, ENil))) |> + DelayList.dropWhile(i -> i < 5) |> + DelayList.dropWhile(i -> checked_ecast(i > 1))) + + @Test + def dropWhileDropWhile04(): Unit \ Assert + IO = + assertEq(expected = ECons(1, ENil), ECons(4, ECons(5, ECons(1, ENil))) |> + DelayList.dropWhile(i -> checked_ecast(i < 5)) |> + DelayList.dropWhile(i -> checked_ecast(i > 1))) + + + ///////////////////////////////////////////////////////////////////////////// + // dropWhile dropWhile fusion // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def dropWhileFusion01(): Unit \ Assert = region rc { + let l = Ref.fresh(rc, Nil); + discard (1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.dropWhile(i -> { Ref.put("a" :: Ref.get(l), l); i < 3 }) |> + DelayList.dropWhile(i -> { Ref.put("b" :: Ref.get(l), l); i < 4 }); + assertEq(expected = ("a" :: "a" :: "a" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + @Test + def dropWhileFusion02(): Unit \ Assert + IO = region rc { + let l = Ref.fresh(rc, Nil); + discard checked_ecast((1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.dropWhile(i -> unchecked_cast({ Ref.put("a" :: Ref.get(l), l); i < 3 } as _ \ {})) |> + DelayList.dropWhile(i -> unchecked_cast({ Ref.put("b" :: Ref.get(l), l); i < 4 } as _ \ {})) |> + DelayList.toList); + assertEq(expected = ("a" :: "a" :: "a" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + @Test + def dropWhileFusion03(): Unit \ Assert + IO = region rc { + let l = Ref.fresh(rc, Nil); + discard checked_ecast((1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.dropWhile(i -> unchecked_cast({ Ref.put("a" :: Ref.get(l), l); i < 1 } as _ \ {})) |> + DelayList.dropWhile(i -> unchecked_cast({ Ref.put("b" :: Ref.get(l), l); i < 3 } as _ \ {})) |> + DelayList.toList); + assertEq(expected = ("a" :: "b" :: "b" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + @Test + def dropWhileFusion04(): Unit \ Assert + IO = region rc { + let l = Ref.fresh(rc, Nil); + discard checked_ecast((1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.dropWhile(i -> unchecked_cast({ Ref.put("a" :: Ref.get(l), l); i < 2 } as _ \ {})) |> + DelayList.dropWhile(i -> unchecked_cast({ Ref.put("b" :: Ref.get(l), l); i < 3 } as _ \ {})) |> + DelayList.toList); + assertEq(expected = ("a" :: "a" :: "b" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + ///////////////////////////////////////////////////////////////////////////// + // findMap // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def findMap01(): Unit \ Assert = + assertEq(expected = None, DelayList.findMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, ENil)) + + @Test + def findMap02(): Unit \ Assert = + assertEq(expected = None, DelayList.findMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, ECons(1, ENil))) + + @Test + def findMap03(): Unit \ Assert = + assertEq(expected = Some(1), DelayList.findMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, ECons(2, ENil))) + + @Test + def findMap04(): Unit \ Assert = + assertEq(expected = None, DelayList.findMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, ECons(1, ECons(3, ENil)))) + + @Test + def findMap05(): Unit \ Assert = + assertEq(expected = Some(2), DelayList.findMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, ECons(1, ECons(4, ENil)))) + + @Test + def findMap06(): Unit \ Assert = + assertEq(expected = Some(3), DelayList.findMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, ECons(6, ECons(-1, ENil)))) + + @Test + def findMap07(): Unit \ Assert = + assertEq(expected = Some(4), DelayList.findMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, ECons(8, ECons(6, ENil)))) + + @Test + def findMap08(): Unit \ Assert = + let l = DelayList.findMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, ECons(0, ECons(1, ECons(2, ECons(3, ECons(4, ECons(5, ECons(10, ENil)))))))); + assertEq(expected = Some(0), l) + + @Test + def findMap09(): Unit \ Assert = + let l = DelayList.findMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, + LList(lazy LCons(-1, lazy LList(lazy LCons(1, lazy + LList(lazy LCons(9, lazy LList(lazy LCons(3, lazy + LList(lazy LCons(5, lazy LList(lazy LCons(5, lazy + LList(lazy LCons(10, lazy LList(lazy ENil)))))))))))))))); + assertEq(expected = Some(5), l) + + + ///////////////////////////////////////////////////////////////////////////// + // filterMap (pure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def filterMapPure01(): Unit \ Assert = + assertEq(expected = ENil, DelayList.filterMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, ENil)) + + @Test + def filterMapPure02(): Unit \ Assert = + assertEq(expected = ENil, DelayList.filterMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, ECons(1, ENil))) + + @Test + def filterMapPure03(): Unit \ Assert = + assertEq(expected = ECons(1, ENil), DelayList.filterMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, ECons(2, ENil))) + + @Test + def filterMapPure04(): Unit \ Assert = + assertEq(expected = ENil, DelayList.filterMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, ECons(1, ECons(3, ENil)))) + + @Test + def filterMapPure05(): Unit \ Assert = + assertEq(expected = ECons(2, ENil), DelayList.filterMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, ECons(1, ECons(4, ENil)))) + + @Test + def filterMapPure06(): Unit \ Assert = + assertEq(expected = ECons(3, ENil), DelayList.filterMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, ECons(6, ECons(-1, ENil)))) + + @Test + def filterMapPure07(): Unit \ Assert = + assertEq(expected = ECons(4, ECons(3, ENil)), DelayList.filterMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, ECons(8, ECons(6, ENil)))) + + @Test + def filterMapPure08(): Unit \ Assert = + let l = DelayList.filterMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, ECons(0, ECons(1, ECons(2, ECons(3, ECons(4, ECons(5, ECons(10, ENil)))))))); + assertEq(expected = ECons(0, ECons(1, ECons(2, ECons(5, ENil)))), l) + + @Test + def filterMapPure09(): Unit \ Assert = + let l = DelayList.filterMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None, + LList(lazy LCons(0, lazy LList(lazy + LCons(1, lazy LList(lazy LCons(2, lazy + LList(lazy LCons(3, lazy LList(lazy + LCons(4, lazy LList(lazy LCons(5, lazy + LList(lazy LCons(10, lazy LList(lazy ENil)))))))))))))))); + assertEq(expected = ECons(0, ECons(1, ECons(2, ECons(5, ENil)))), l) + + + ///////////////////////////////////////////////////////////////////////////// + // filterMap (impure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def filterMapImpure01(): Unit \ Assert + IO = + assertEq(expected = ENil, DelayList.filterMap(i -> checked_ecast(if (i `Int32.remainder` 2 == 0) Some(i / 2) else None), ENil)) + + @Test + def filterMapImpure02(): Unit \ Assert + IO = + assertEq(expected = ENil, DelayList.filterMap(i -> checked_ecast(if (i `Int32.remainder` 2 == 0) Some(i / 2) else None), ECons(1, ENil))) + + @Test + def filterMapImpure03(): Unit \ Assert + IO = + assertEq(expected = ECons(1, ENil), DelayList.filterMap(i -> checked_ecast(if (i `Int32.remainder` 2 == 0) Some(i / 2) else None), ECons(2, ENil))) + + @Test + def filterMapImpure04(): Unit \ Assert + IO = + assertEq(expected = ENil, DelayList.filterMap(i -> checked_ecast(if (i `Int32.remainder` 2 == 0) Some(i / 2) else None), ECons(1, ECons(3, ENil)))) + + @Test + def filterMapImpure05(): Unit \ Assert + IO = + assertEq(expected = ECons(2, ENil), DelayList.filterMap(i -> checked_ecast(if (i `Int32.remainder` 2 == 0) Some(i / 2) else None), ECons(1, ECons(4, ENil)))) + + @Test + def filterMapImpure06(): Unit \ Assert + IO = + assertEq(expected = ECons(3, ENil), DelayList.filterMap(i -> checked_ecast(if (i `Int32.remainder` 2 == 0) Some(i / 2) else None), ECons(6, ECons(-1, ENil)))) + + @Test + def filterMapImpure07(): Unit \ Assert + IO = + assertEq(expected = ECons(4, ECons(3, ENil)), DelayList.filterMap(i -> checked_ecast(if (i `Int32.remainder` 2 == 0) Some(i / 2) else None), ECons(8, ECons(6, ENil)))) + + @Test + def filterMapImpure08(): Unit \ Assert + IO = + let l = DelayList.filterMap(i -> checked_ecast(if (i `Int32.remainder` 2 == 0) Some(i / 2) else None), ECons(0, ECons(1, ECons(2, ECons(3, ECons(4, ECons(5, ECons(10, ENil)))))))); + assertEq(expected = ECons(0, ECons(1, ECons(2, ECons(5, ENil)))), l) + + @Test + def filterMapImpure09(): Unit \ Assert + IO = + let l = DelayList.filterMap(i -> checked_ecast(if (i `Int32.remainder` 2 == 0) Some(i / 2) else None), + LList(lazy LCons(0, lazy LList(lazy + LCons(1, lazy LList(lazy LCons(2, lazy + LList(lazy LCons(3, lazy LList(lazy + LCons(4, lazy LList(lazy LCons(5, lazy + LList(lazy LCons(10, lazy LList(lazy ENil)))))))))))))))); + assertEq(expected = ECons(0, ECons(1, ECons(2, ECons(5, ENil)))), l) + + + ///////////////////////////////////////////////////////////////////////////// + // filterMap filterMap // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def filterMapFilterMap01(): Unit \ Assert = + let l = ECons(2, ECons(4, ECons(6, ECons(7, ENil)))) |> + DelayList.filterMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None) |> + DelayList.filterMap(i -> if (i > 1) Some(i * 3) else None); + assertEq(expected = ECons(6, ECons(9, ENil)), l) + + @Test + def filterMapFilterMap02(): Unit \ Assert + IO = + let l = ECons(2, ECons(4, ECons(6, ECons(7, ENil)))) |> + DelayList.filterMap(i -> checked_ecast(if (i `Int32.remainder` 2 == 0) Some(i / 2) else None)) |> + DelayList.filterMap(i -> if (i > 1) Some(i * 3) else None); + assertEq(expected = ECons(6, ECons(9, ENil)), l) + + @Test + def filterMapFilterMap03(): Unit \ Assert + IO = + let l = ECons(2, ECons(4, ECons(6, ECons(7, ENil)))) |> + DelayList.filterMap(i -> if (i `Int32.remainder` 2 == 0) Some(i / 2) else None) |> + DelayList.filterMap(i -> checked_ecast(if (i > 1) Some(i * 3) else None)); + assertEq(expected = ECons(6, ECons(9, ENil)), l) + + @Test + def filterMapFilterMap04(): Unit \ Assert + IO = + let l = ECons(2, ECons(4, ECons(6, ECons(7, ENil)))) |> + DelayList.filterMap(i -> checked_ecast(if (i `Int32.remainder` 2 == 0) Some(i / 2) else None)) |> + DelayList.filterMap(i -> checked_ecast(if (i > 1) Some(i * 3) else None)); + assertEq(expected = ECons(6, ECons(9, ENil)), l) + + + ///////////////////////////////////////////////////////////////////////////// + // filterMap filterMap fusion // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def filterMapFusion01(): Unit \ Assert = region rc { + let l = Ref.fresh(rc, Nil); + discard (1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.filterMap(x -> { Ref.put("a" :: Ref.get(l), l); Some(x) }) |> + DelayList.filterMap(x -> { Ref.put("b" :: Ref.get(l), l); Some(x) }); + assertEq(expected = ("a" :: "a" :: "a" :: "b" :: "b" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + @Test + def filterMapFusion02(): Unit \ Assert + IO = region rc { + let l = Ref.fresh(rc, Nil); + discard checked_ecast((1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.filterMap(x -> unchecked_cast({ Ref.put("a" :: Ref.get(l), l); Some(x) } as _ \ {})) |> + DelayList.filterMap(x -> unchecked_cast({ Ref.put("b" :: Ref.get(l), l); Some(x) } as _ \ {})) |> + DelayList.toList); + assertEq(expected = ("a" :: "b" :: "a" :: "b" :: "a" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + ///////////////////////////////////////////////////////////////////////////// + // partition // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def partition01(): Unit \ Assert = + assertEq(expected = (ENil, ENil), DelayList.partition(i -> i > 3, ENil)) + + @Test + def partition02(): Unit \ Assert = + assertEq(expected = (ENil, ECons(1, ENil)), DelayList.partition(i -> i > 3, ECons(1, ENil))) + + @Test + def partition03(): Unit \ Assert = + assertEq(expected = (ECons(4, ENil), ENil), DelayList.partition(i -> i > 3, ECons(4, ENil))) + + @Test + def partition04(): Unit \ Assert = + assertEq(expected = (ENil, ECons(1, ECons(2, ENil))), DelayList.partition(i -> i > 3, ECons(1, ECons(2, ENil)))) + + @Test + def partition05(): Unit \ Assert = + assertEq(expected = (ECons(5, ENil), ECons(1, ENil)), DelayList.partition(i -> i > 3, ECons(1, ECons(5, ENil)))) + + @Test + def partition06(): Unit \ Assert = + assertEq(expected = (ECons(5, ENil), ECons(1, ENil)), DelayList.partition(i -> i > 3, ECons(5, ECons(1, ENil)))) + + @Test + def partition07(): Unit \ Assert = + assertEq(expected = (ECons(5, ECons(8, ENil)), ENil), DelayList.partition(i -> i > 3, ECons(5, ECons(8, ENil)))) + + @Test + def partition08(): Unit \ Assert = + let l = DelayList.partition(i -> i > 3, ECons(4, ECons(6, ECons(-3, ECons(11, ECons(-5, ECons(1, ECons(2, ECons(16, ECons(7, ECons(1, ECons(7, ENil)))))))))))); + assertEq(expected = (ECons(4, ECons(6, ECons(11, ECons(16, ECons(7, ECons(7, ENil)))))), ECons(-3, ECons(-5, ECons(1, ECons(2, ECons(1, ENil)))))), l) + + @Test + def partition09(): Unit \ Assert = + let l = DelayList.partition(i -> i > 3, + LList(lazy LCons(4, lazy LList(lazy + ECons(6, LCons(-3, lazy LList(lazy + LCons(11, lazy LList(lazy LCons(-5, lazy + LList(lazy LCons(1, lazy LList(lazy + LCons(2, lazy LList(lazy LCons(16, lazy + LList(lazy LCons(7, lazy LList(lazy + LCons(1, lazy LList(lazy LCons(7, lazy LList(lazy ENil))))))))))))))))))))))); + assertEq(expected = (ECons(4, ECons(6, ECons(11, ECons(16, ECons(7, ECons(7, ENil)))))), + ECons(-3, ECons(-5, ECons(1, ECons(2, ECons(1, ENil)))))), l) + + + ///////////////////////////////////////////////////////////////////////////// + // span // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def span01(): Unit \ Assert = + assertEq(expected = (ENil, ENil), DelayList.span(i -> i > 3, ENil)) + + @Test + def span02(): Unit \ Assert = + assertEq(expected = (ENil, ECons(1, ENil)), DelayList.span(i -> i > 3, ECons(1, ENil))) + + @Test + def span03(): Unit \ Assert = + assertEq(expected = (ECons(4, ENil), ENil), DelayList.span(i -> i > 3, ECons(4, ENil))) + + @Test + def span04(): Unit \ Assert = + assertEq(expected = (ENil, ECons(1, ECons(2, ENil))), DelayList.span(i -> i > 3, ECons(1, ECons(2, ENil)))) + + @Test + def span05(): Unit \ Assert = + assertEq(expected = (ENil, ECons(1, ECons(5, ENil))), DelayList.span(i -> i > 3, ECons(1, ECons(5, ENil)))) + + @Test + def span06(): Unit \ Assert = + assertEq(expected = (ECons(5, ENil), ECons(1, ENil)), DelayList.span(i -> i > 3, ECons(5, ECons(1, ENil)))) + + @Test + def span07(): Unit \ Assert = + assertEq(expected = (ECons(5, ECons(8, ENil)), ENil), DelayList.span(i -> i > 3, ECons(5, ECons(8, ENil)))) + + @Test + def span08(): Unit \ Assert = + let l = DelayList.span(i -> i > 3, ECons(4, ECons(6, ECons(-3, ECons(11, ECons(-5, ECons(1, ECons(2, ECons(16, ECons(7, ECons(1, ECons(7, ENil)))))))))))); + assertEq(expected = (ECons(4, ECons(6, ENil)), ECons(-3, ECons(11, ECons(-5, ECons(1, ECons(2, ECons(16, ECons(7, ECons(1, ECons(7, ENil)))))))))), l) + + @Test + def span09(): Unit \ Assert = + let l = DelayList.span(i -> i > 3, + LList(lazy LCons(4, lazy LList(lazy + LCons(6, lazy LList(lazy LCons(-3, lazy + LList(lazy LCons(11, lazy LList(lazy + LCons(-5, lazy LList(lazy LCons(1, lazy + LList(lazy LCons(2, lazy LList(lazy + LCons(16, lazy LList(lazy LCons(7, lazy + LList(lazy LCons(1, lazy LList(lazy + LCons(7, lazy LList(lazy ENil)))))))))))))))))))))))); + assertEq(expected = (ECons(4, ECons(6, ENil)), + ECons(-3, ECons(11, ECons(-5, ECons(1, ECons(2, ECons(16, ECons(7, ECons(1, ECons(7, ENil)))))))))), l) + + + ///////////////////////////////////////////////////////////////////////////// + // span span fusion // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def spanSpanFusion01(): Unit \ Assert = region rc { + let l = Ref.fresh(rc, Nil); + discard (1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.span(x -> { Ref.put("a" :: Ref.get(l), l); x < 3 }) |> fst |> + DelayList.span(x -> { Ref.put("b" :: Ref.get(l), l); x < 3 }); // The working list is `1 :: 2 :: Nil` + assertEq(expected = ("a" :: "a" :: "a" :: "b" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + ///////////////////////////////////////////////////////////////////////////// + // sum // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def sum01(): Unit \ Assert = + assertEq(expected = 0, toDelayList(Nil) |> DelayList.sum) + + @Test + def sum02(): Unit \ Assert = + assertEq(expected = 1, toDelayList(1 :: Nil) |> DelayList.sum) + + @Test + def sum03(): Unit \ Assert = + assertEq(expected = 6, toDelayList(1 :: 2 :: 3 :: Nil) |> DelayList.sum) + + @Test + def sum04(): Unit \ Assert = + assertEq(expected = 3, toDelayList(1 :: 2 :: 3 :: -3 :: Nil) |> DelayList.sum) + + @Test + def sum05(): Unit \ Assert = + assertEq(expected = -10, toDelayList(-1 :: -2 :: -3 :: -4 :: Nil) |> DelayList.sum) + + @Test + def sum06(): Unit \ Assert = + assertEq(expected = 0, toDelayList(10 :: -10 :: Nil) |> DelayList.sum) + + @Test + def sum07(): Unit \ Assert = + assertEq(expected = 5050, List.range(1, 101) |> toDelayList |> DelayList.sum) + + + ///////////////////////////////////////////////////////////////////////////// + // sumWith // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def sumWith01(): Unit \ Assert = + assertEq(expected = 0, toDelayList(Nil) |> DelayList.sumWith(x -> x + 1)) + + @Test + def sumWith02(): Unit \ Assert = + assertEq(expected = 2, toDelayList(1 :: Nil) |> DelayList.sumWith(x -> x + 1)) + + @Test + def sumWith03(): Unit \ Assert = + assertEq(expected = 9, toDelayList(1 :: 2 :: 3 :: Nil) |> DelayList.sumWith(x -> x + 1)) + + @Test + def sumWith04(): Unit \ Assert = + assertEq(expected = 7, toDelayList(1 :: 2 :: 3 :: -3 :: Nil) |> DelayList.sumWith(x -> x + 1)) + + @Test + def sumWith05(): Unit \ Assert = + assertEq(expected = -6, toDelayList(-1 :: -2 :: -3 :: -4 :: Nil) |> DelayList.sumWith(x -> x + 1)) + + @Test + def sumWith06(): Unit \ Assert = + assertEq(expected = 2, toDelayList(10 :: -10 :: Nil) |> DelayList.sumWith(x -> x + 1)) + + + ///////////////////////////////////////////////////////////////////////////// + // order // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def order01(): Unit \ Assert = + assertEq(expected = Comparison.EqualTo, (ENil: DelayList[Unit]) <=> (ENil: DelayList[Unit])) + + @Test + def order02(): Unit \ Assert = + assertEq(expected = Comparison.GreaterThan, ((1 :: Nil) |> toDelayList) <=> (ENil: DelayList[Int32])) + + @Test + def order03(): Unit \ Assert = + assertEq(expected = Comparison.LessThan, (ENil: DelayList[Int32]) <=> ((1 :: Nil) |> toDelayList)) + + @Test + def order04(): Unit \ Assert = + assertEq(expected = Comparison.EqualTo, ((1 :: Nil) |> toDelayList) <=> ((1 :: Nil) |> toDelayList)) + + @Test + def order05(): Unit \ Assert = + assertEq(expected = Comparison.GreaterThan, ((2 :: 1 :: Nil) |> toDelayList) <=> ((1 :: 1 :: Nil) |> toDelayList)) + + @Test + def order06(): Unit \ Assert = + assertEq(expected = Comparison.LessThan, ((1 :: 1 :: Nil) |> toDelayList) <=> ((2 :: 1 :: Nil) |> toDelayList)) + + @Test + def order07(): Unit \ Assert = + assertEq(expected = Comparison.LessThan, ((1 :: Nil) |> toDelayList) <=> ((1 :: 1 :: Nil) |> toDelayList)) + + + ///////////////////////////////////////////////////////////////////////////// + // join // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def join01(): Unit \ Assert = + assertEq(expected = "", (Nil: List[Int32]) |> toDelayList |> + DelayList.join(",")) + + @Test + def join02(): Unit \ Assert = + assertEq(expected = "1", (1 :: Nil) |> toDelayList |> + DelayList.join(",")) + + @Test + def join03(): Unit \ Assert = + assertEq(expected = "1,2,3", (1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.join(",")) + + @Test + def join04(): Unit \ Assert = + assertEq(expected = "1,2,3", ("1" :: "2" :: "3" :: Nil) |> toDelayList |> + DelayList.join(",")) + + + ///////////////////////////////////////////////////////////////////////////// + // joinWith // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def joinWith01(): Unit \ Assert = + assertEq(expected = "", (Nil: List[Int32]) |> toDelayList |> + DelayList.joinWith(x -> "${x + 1}", ",")) + + @Test + def joinWith02(): Unit \ Assert = + assertEq(expected = "2", (1 :: Nil) |> toDelayList |> + DelayList.joinWith(x -> "${x + 1}", ",")) + + @Test + def joinWith03(): Unit \ Assert = + assertEq(expected = "2,3,4", (1 :: 2 :: 3 :: Nil) |> toDelayList |> + DelayList.joinWith(x -> "${x + 1}", ",")) + + @Test + def joinWith04(): Unit \ Assert = + assertEq(expected = "11,22,33", ("1" :: "2" :: "3" :: Nil) |> toDelayList |> + DelayList.joinWith(x -> x + x, ",")) + + + ///////////////////////////////////////////////////////////////////////////// + // ap // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def ap01(): Unit \ Assert = + assertEq(expected = (ENil: DelayList[Int32]), DelayList.ap(ENil, ENil)) + + @Test + def ap02(): Unit \ Assert = + assertEq(expected = ENil, DelayList.ap(ECons((x -> x + 1), ENil), ENil)) + + @Test + def ap03(): Unit \ Assert = + assertEq(expected = (ENil: DelayList[Int32]), DelayList.ap(ENil, ECons(5, ENil))) + + @Test + def ap04(): Unit \ Assert = + assertEq(expected = 6 :: Nil, DelayList.ap(ECons((x -> x + 1), ENil), ECons(5, ENil)) |> DelayList.toList) + + @Test + def ap05(): Unit \ Assert = + let f = toDelayList((x -> x + 1) :: Nil); + let l = toDelayList(0 :: 5 :: Nil); + assertEq(expected = 1 :: 6 :: Nil, DelayList.ap(f, l) |> DelayList.toList) + + @Test + def ap06(): Unit \ Assert = + let f = toDelayList((x -> x + 1) :: (x -> x * 2) :: Nil); + let l = toDelayList(0 :: 4 :: Nil); + assertEq(expected = 1 :: 5 :: 0 :: 8 :: Nil, DelayList.ap(f, l) |> DelayList.toList) + + ///////////////////////////////////////////////////////////////////////////// + // sequence // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def sequence01(): Unit \ Assert = + let l: DelayList[Identity[Int32]] = ENil; + assertEq(expected = Identity.Identity(ENil), DelayList.sequence(l)) + + @Test + def sequence02(): Unit \ Assert = + let l = toDelayList(Identity.Identity(1) :: Nil); + assertEq(expected = Identity.Identity(toDelayList(1 :: Nil)), DelayList.sequence(l)) + + @Test + def sequence03(): Unit \ Assert = + let l = toDelayList(Identity.Identity(1) :: Identity.Identity(2) :: Nil); + assertEq(expected = Identity.Identity(toDelayList(1 :: 2 :: Nil)), DelayList.sequence(l)) + + @Test + def sequence04(): Unit \ Assert = + let l = toDelayList(Identity.Identity(1) :: Identity.Identity(2) :: Identity.Identity(3) :: Nil); + assertEq(expected = Identity.Identity(toDelayList(1 :: 2 :: 3 :: Nil)), DelayList.sequence(l)) + + ///////////////////////////////////////////////////////////////////////////// + // traverse // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def traverse01(): Unit \ Assert = region rc { + let st = Ref.fresh(rc, 0); + let l = ENil; + let ans = DelayList.traverse(x -> {Ref.put(x, st); Identity.Identity(x)}, l); + assertEq(expected = Identity.Identity(ENil), ans); + assertEq(expected = 0, Ref.get(st)) + } + + @Test + def traverse02(): Unit \ Assert = region rc { + let st = Ref.fresh(rc, 0); + let l = toDelayList(1 :: Nil); + let ans = DelayList.traverse(x -> {Ref.put(x, st); Identity.Identity(x)}, l); + assertEq(expected = Identity.Identity(toDelayList(1 :: Nil)), ans); + assertEq(expected = 1, Ref.get(st)) + } + + @Test + def traverse03(): Unit \ Assert = region rc { + let st = Ref.fresh(rc, 0); + let l = toDelayList(1 :: 2 :: Nil); + let ans = DelayList.traverse(x -> {Ref.put(x, st); Identity.Identity(x)}, l); + assertEq(expected = Identity.Identity(toDelayList(1 :: 2 :: Nil)), ans); + assertEq(expected = 2, Ref.get(st)) + } + + @Test + def traverse04(): Unit \ Assert = region rc { + let st = Ref.fresh(rc, 0); + let l = toDelayList(1 :: 2 :: 3 :: Nil); + let ans = DelayList.traverse(x -> {Ref.put(x, st); Identity.Identity(x)}, l); + assertEq(expected = Identity.Identity(toDelayList(1 :: 2 :: 3 :: Nil)), ans); + assertEq(expected = 3, Ref.get(st)) + } + + ///////////////////////////////////////////////////////////////////////////// + // shuffle // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def shuffle01(): Unit \ Assert + NonDet = + run { + let l1: List[Int32] = Nil; + let l2 = toDelayList(l1) |> DelayList.shuffle; + + assertEq(expected = 0, DelayList.length(l2)); + assertEq(expected = Set#{}, DelayList.toSet(l2)) + } with Shuffle.runWithIO + + @Test + def shuffle02(): Unit \ Assert + NonDet = + run { + let l1 = 1 :: Nil; + let l2 = toDelayList(l1) |> DelayList.shuffle; + + assertEq(expected = 1, DelayList.length(l2)); + assertEq(expected = Set#{1}, DelayList.toSet(l2)) + } with Shuffle.runWithIO + + @Test + def shuffle03(): Unit \ Assert + NonDet = + run { + let l1 = 1 :: 2 :: 3 :: Nil; + let l2 = toDelayList(l1) |> DelayList.shuffle; + + assertEq(expected = 3, DelayList.length(l2)); + assertEq(expected = Set#{1, 2, 3}, DelayList.toSet(l2)) + } with Shuffle.runWithIO + + @Test + def shuffle04(): Unit \ Assert + NonDet = + run { + let l1 = 0 :: 1 :: 2 :: 3 :: 4 :: 5 :: 6 :: 7 :: 8 :: 9 :: Nil; + let l2 = toDelayList(l1) |> DelayList.shuffle; + + assertEq(expected = 10, DelayList.length(l2)); + assertEq(expected = Set#{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, DelayList.toSet(l2)) + } with Shuffle.runWithIO + + + ///////////////////////////////////////////////////////////////////////////// + // toString // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def toString01(): Unit \ Assert = + assertEq(expected = "DelayList(1)", ToString.toString(toDelayList(1 :: Nil))) + + @Test + def toString02(): Unit \ Assert = + assertEq(expected = "DelayList(1, 2)", ToString.toString(toDelayList(1 :: 2 :: Nil))) + + @Test + def toString03(): Unit \ Assert = + assertEq(expected = "DelayList(93, 3, 4)", ToString.toString(toDelayList(93 :: 3 :: 4 :: Nil))) + + @Test + def toString04(): Unit \ Assert = + assertEq(expected = "DelayList(a, b, c)", ToString.toString(toDelayList('a' :: 'b' :: 'c' :: Nil))) + + @Test + def toString05(): Unit \ Assert = + assertEq(expected = "DelayList(true, false, true, true)", ToString.toString(toDelayList(true :: false :: true :: true :: Nil))) + + @Test + def toString06(): Unit \ Assert = + assertEq(expected = "DelayList(DelayList(1, 2), DelayList(2, 3), DelayList(4, 7))", ToString.toString(toDelayList(toDelayList(1 :: 2 :: Nil) :: toDelayList(2 :: 3 :: Nil) :: toDelayList(4 :: 7 :: Nil) :: Nil))) + +} diff --git a/test/TestDelayMap.flix b/test/TestDelayMap.flix new file mode 100644 index 0000000..8e994b5 --- /dev/null +++ b/test/TestDelayMap.flix @@ -0,0 +1,1829 @@ +mod TestDelayMap { + + use Assert.{assertEq, assertTrue}; + use Extras.DelayMap + + /// + /// Returns `m` as a `DelayMap`. + /// + def toDelayMap(m: Map[k, v]): DelayMap[k, v] = + let Map.Map(t) = m; + let f = (_, v) -> lazy v; + DelayMap.DMap(RedBlackTree.mapWithKey(f, t)) + + ///////////////////////////////////////////////////////////////////////////// + // insertWith // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def insertWith01(): Unit \ Assert = + assertEq(expected = (1, 3) :: Nil, DelayMap.insertWith((v1, v2) -> v1 + v2, 1, 3, DelayMap.empty()) |> DelayMap.toList) + + @Test + def insertWith02(): Unit \ Assert = + assertEq(expected = (1, 7) :: Nil, toDelayMap(List.toMap((1, 4) :: Nil)) |> DelayMap.insertWith((v1, v2) -> v1 + v2, 1, 3) |> DelayMap.toList) + + @Test + def insertWith03(): Unit \ Assert = + assertEq(expected = (1, 4) :: (2, 3) :: Nil, toDelayMap(List.toMap((1, 4) :: Nil)) |> DelayMap.insertWith((v1, v2) -> v1 + v2, 2, 3) |> DelayMap.toList) + + @Test + def insertWith04(): Unit \ Assert = + assertEq(expected = (1, 5) :: (5, -2) :: Nil, toDelayMap(List.toMap((1, 4) :: (5, -2) :: Nil)) |> DelayMap.insertWith((v1, v2) -> v1 + v2, 1, 1) |> DelayMap.toList) + + @Test + def insertWith05(): Unit \ Assert = + assertEq(expected = (1, 4) :: (5, -1) :: Nil, toDelayMap(List.toMap((1, 4) :: (5, -2) :: Nil)) |> + DelayMap.insertWith((v1, v2) -> v1 + v2, 5, 1) |> DelayMap.toList) + + @Test + def insertWith06(): Unit \ Assert = + assertEq(expected = (1, 4) :: (4, -2) :: (5, -2):: Nil, toDelayMap(List.toMap((1, 4) :: (5, -2) :: Nil)) |> + DelayMap.insertWith((v1, v2) -> v1 + v2, 4, -2) |> + DelayMap.toList |> List.sortBy(t -> fst(t))) + + + ///////////////////////////////////////////////////////////////////////////// + // insertWithKey insertWithKey // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def insertWithInsertWith01(): Unit \ Assert = + assertEq(expected = ("a", 1) :: ("b", 4) :: Nil, (("a", 1) :: Nil) |> + List.toMap |> + toDelayMap |> + DelayMap.insertWith((v1, v2) -> v1 + v2, "b", 1) |> + DelayMap.insertWith((v1, v2) -> v1 + v2, "b", 3) |> + DelayMap.toList) + + @Test + def insertWithInsertWith02(): Unit \ {Assert, IO} = + assertEq(expected = ("a", 1) :: ("b", 4) :: Nil, (("a", 1) :: Nil) |> + List.toMap |> + toDelayMap |> + DelayMap.insertWith((v1, v2) -> v1 + v2, unchecked_cast("b" as _ \ IO), 1) |> + DelayMap.insertWith((v1, v2) -> v1 + v2, "b", 3) |> + DelayMap.toList) + @Test + def insertWithInsertWith03(): Unit \ {Assert, IO} = + assertEq(expected = ("a", 1) :: ("b", 4) :: Nil, (("a", 1) :: Nil) |> + List.toMap |> + toDelayMap |> + DelayMap.insertWith((v1, v2) -> v1 + v2, "b", 1) |> + DelayMap.insertWith((v1, v2) -> v1 + v2, unchecked_cast("b" as _ \ IO), 3) |> + DelayMap.toList) + + @Test + def insertWithInsertWith04(): Unit \ {Assert, IO} = + assertEq(expected = ("a", 1) :: ("b", 4) :: Nil, (("a", 1) :: Nil) |> + List.toMap |> + toDelayMap |> + DelayMap.insertWith((v1, v2) -> v1 + v2, unchecked_cast("b" as _ \ IO), 1) |> + DelayMap.insertWith((v1, v2) -> v1 + v2, unchecked_cast("b" as _ \ IO), 3) |> + DelayMap.toList) + + + ///////////////////////////////////////////////////////////////////////////// + // insertWith insertWith fusion // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def insertWithFusion01(): Unit \ Assert = region rc { + let l = Ref.fresh(rc, Nil); + discard toDelayMap(List.toMap((1, 1) :: Nil)) |> + DelayMap.insertWith((v, _) -> { Ref.put("a" :: Ref.get(l), l); v }, 1, 1) |> + DelayMap.insertWith((v, _) -> { Ref.put("a" :: Ref.get(l), l); v }, 1, 1) |> + DelayMap.insertWith((v, _) -> { Ref.put("a" :: Ref.get(l), l); v }, 1, 1) |> + DelayMap.insertWith((v, _) -> { Ref.put("b" :: Ref.get(l), l); v }, 1, 1) |> + DelayMap.insertWith((v, _) -> { Ref.put("b" :: Ref.get(l), l); v }, 1, 1) |> + DelayMap.insertWith((v, _) -> { Ref.put("b" :: Ref.get(l), l); v }, 1, 1); + assertEq(expected = "a" :: "a" :: "a" :: "b" :: "b" :: "b" :: Nil, List.reverse(Ref.get(l))) + } + + ///////////////////////////////////////////////////////////////////////////// + // count // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def count01(): Unit \ Assert = + let m = (Map#{}: Map[Unit, Unit]) |> toDelayMap; + assertEq(expected = 0, DelayMap.count((k, v) -> k == v, m)) + + @Test + def count02(): Unit \ Assert = + let m = Map#{1 => 2} |> toDelayMap; + assertEq(expected = 0, DelayMap.count((k, v) -> k == v, m)) + + @Test + def count03(): Unit \ Assert = + let m = Map#{1 => 1} |> toDelayMap; + assertEq(expected = 1, DelayMap.count((k, v) -> k == v, m)) + + @Test + def count04(): Unit \ Assert = + let m = Map#{1 => 2, 2 => 3} |> toDelayMap; + assertEq(expected = 0, DelayMap.count((k, v) -> k == v, m)) + + @Test + def count05(): Unit \ Assert = + let m = Map#{1 => 1, 2 => 3} |> toDelayMap; + assertEq(expected = 1, DelayMap.count((k, v) -> k == v, m)) + + @Test + def count06(): Unit \ Assert = + let m = Map#{1 => 2, 2 => 2} |> toDelayMap; + assertEq(expected = 1, DelayMap.count((k, v) -> k == v, m)) + + @Test + def count07(): Unit \ Assert = + let m = Map#{1 => 1, 2 => 2} |> toDelayMap; + assertEq(expected = 2, DelayMap.count((k, v) -> k == v, m)) + + @Test + def count08(): Unit \ Assert = region rc { + let range = List.range(0, 2000); + let m = List.zip(range, range) |> List.toMap |> toDelayMap; + let a = MutList.empty(rc); + discard DelayMap.count((k, _) -> { let b = MutList.empty(rc); MutList.push(k, b); MutList.append(MutList.toList(b), a); true }, m); + assertEq(expected = range, MutList.toList(a)) + } + + + ///////////////////////////////////////////////////////////////////////////// + // map (pure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def mapPure01(): Unit \ Assert = + assertEq(expected = Map#{}, (Map#{}: Map[Unit, Int32]) |> toDelayMap |> DelayMap.map(v -> 3 * v) |> DelayMap.toMap) + + @Test + def mapPure02(): Unit \ Assert = + assertEq(expected = Map#{1 => 12}, Map#{1 => 4} |> toDelayMap |> DelayMap.map(v -> 3 * v) |> DelayMap.toMap) + + @Test + def mapPure03(): Unit \ Assert = + assertEq(expected = Map#{2 => -3, 0 => 0}, Map#{2 => -1, 0 => 0} |> toDelayMap |> + DelayMap.map(v -> 3 * v) |> DelayMap.toMap) + + @Test + def mapPure04(): Unit \ Assert = + assertEq(expected = Map#{2 => -3, 5 => 45, 11 => -27}, Map#{2 => -1, 5 => 15, 11 => -9} |> toDelayMap |> + DelayMap.map(v -> 3 * v) |> DelayMap.toMap) + + @Test + def mapPure05(): Unit \ Assert = + assertEq(expected = Map#{2 => -3, 5 => 45, 11 => -27, 8 => 24}, Map#{2 => -1, 5 => 15, 11 => -9, 8 => 8} |> toDelayMap |> + DelayMap.map(v -> 3 * v) |> DelayMap.toMap) + + + ///////////////////////////////////////////////////////////////////////////// + // map (impure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def mapImpure01(): Unit \ {Assert, IO} = + assertEq(expected = Map#{}, (Map#{}: Map[Unit, Int32]) |> toDelayMap |> + DelayMap.map(v -> unchecked_cast(3 * v as _ \ IO)) |> DelayMap.toMap) + + @Test + def mapImpure02(): Unit \ {Assert, IO} = + assertEq(expected = Map#{1 => 12}, Map#{1 => 4} |> toDelayMap |> + DelayMap.map(v -> unchecked_cast(3 * v as _ \ IO)) |> DelayMap.toMap) + + @Test + def mapImpure03(): Unit \ {Assert, IO} = + assertEq(expected = Map#{2 => -3, 0 => 0}, Map#{2 => -1, 0 => 0} |> toDelayMap |> + DelayMap.map(v -> unchecked_cast(3 * v as _ \ IO)) |> DelayMap.toMap) + + @Test + def mapImpure04(): Unit \ {Assert, IO} = + assertEq(expected = Map#{2 => -3, 5 => 45, 11 => -27}, Map#{2 => -1, 5 => 15, 11 => -9} |> toDelayMap |> + DelayMap.map(v -> unchecked_cast(3 * v as _ \ IO)) |> DelayMap.toMap) + + @Test + def mapImpure05(): Unit \ {Assert, IO} = + assertEq(expected = Map#{2 => -3, 5 => 45, 11 => -27, 8 => 24}, Map#{2 => -1, 5 => 15, 11 => -9, 8 => 8} |> toDelayMap |> + DelayMap.map(v -> unchecked_cast(3 * v as _ \ IO)) |> DelayMap.toMap) + + + ///////////////////////////////////////////////////////////////////////////// + // map map // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def mapMap01(): Unit \ Assert = + assertEq(expected = Map#{2 => -9, 5 => 135, 11 => -81}, Map#{2 => -1, 5 => 15, 11 => -9} |> + toDelayMap |> + DelayMap.map(v -> 3 * v) |> + DelayMap.map(v -> 3 * v) |> + DelayMap.toMap) + + @Test + def mapMap02(): Unit \ {Assert, IO} = + assertEq(expected = Map#{2 => -9, 5 => 135, 11 => -81}, Map#{2 => -1, 5 => 15, 11 => -9} |> + toDelayMap |> + DelayMap.map(v -> unchecked_cast(3 * v as _ \ IO)) |> + DelayMap.map(v -> 3 * v) |> + DelayMap.toMap) + + @Test + def mapMap03(): Unit \ {Assert, IO} = + assertEq(expected = Map#{2 => -9, 5 => 135, 11 => -81}, Map#{2 => -1, 5 => 15, 11 => -9} |> + toDelayMap |> + DelayMap.map(v -> 3 * v) |> + DelayMap.map(v -> unchecked_cast(3 * v as _ \ IO)) |> + DelayMap.toMap) + + @Test + def mapMap04(): Unit \ {Assert, IO} = + assertEq(expected = Map#{2 => -9, 5 => 135, 11 => -81}, Map#{2 => -1, 5 => 15, 11 => -9} |> + toDelayMap |> + DelayMap.map(v -> unchecked_cast(3 * v as _ \ IO)) |> + DelayMap.map(v -> unchecked_cast(3 * v as _ \ IO)) |> + DelayMap.toMap) + + + ///////////////////////////////////////////////////////////////////////////// + // map (fusion) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def mapFusion01(): Unit \ Assert = region rc { + let l = Ref.fresh(rc, Nil); + discard ((1, 1) :: (2, 2) :: (3, 3) :: Nil) |> List.toMap |> toDelayMap |> + DelayMap.map(v -> { Ref.put("a" :: Ref.get(l), l); v }) |> + DelayMap.map(v -> { Ref.put("b" :: Ref.get(l), l); v }); + assertEq(expected = "a" :: "a" :: "a" :: "b" :: "b" :: "b" :: Nil, List.reverse(Ref.get(l))) + } + + ///////////////////////////////////////////////////////////////////////////// + // mapWithKey // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def mapWithKey01(): Unit \ Assert = + assertEq(expected = Map#{}, (Map#{}: Map[Unit, Unit]) |> toDelayMap |> + DelayMap.mapWithKey((_, v) -> v) |> DelayMap.toMap) + + @Test + def mapWithKey02(): Unit \ Assert = + assertEq(expected = Map#{1 => 5}, Map#{1 => 4} |> toDelayMap |> + DelayMap.mapWithKey((k, v) -> k + v) |> DelayMap.toMap) + + @Test + def mapWithKey03(): Unit \ Assert = + assertEq(expected = Map#{2 => 1, 0 => 0}, Map#{2 => -1, 0 => 0} |> toDelayMap |> + DelayMap.mapWithKey((k, v) -> k + v) |> DelayMap.toMap) + + @Test + def mapWithKey04(): Unit \ Assert = + assertEq(expected = Map#{2 => 1, 5 => 20, 11 => 2}, Map#{2 => -1, 5 => 15, 11 => -9} |> toDelayMap |> + DelayMap.mapWithKey((k, v) -> k + v) |> DelayMap.toMap) + + @Test + def mapWithKey05(): Unit \ Assert = + assertEq(expected = Map#{2 => 1, 5 => 20, 11 => 2, 8 => 16}, Map#{2 => -1, 5 => 15, 11 => -9, 8 => 8} |> toDelayMap |> + DelayMap.mapWithKey((k, v) -> k + v) |> DelayMap.toMap) + + + ///////////////////////////////////////////////////////////////////////////// + // union // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def union01(): Unit \ Assert = + let m1 = toDelayMap((Map#{}: Map[Unit, Unit])); + let m2 = toDelayMap(Map#{}); + assertEq(expected = Map#{}, DelayMap.union(m1, m2) |> DelayMap.toMap) + + @Test + def union02(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2}); + let m2 = toDelayMap(Map#{}); + assertEq(expected = Map#{1 => 2}, DelayMap.union(m1, m2) |> DelayMap.toMap) + + @Test + def union03(): Unit \ Assert = + let m1 = toDelayMap(Map#{}); + let m2 = toDelayMap(Map#{1 => 2}); + assertEq(expected = Map#{1 => 2}, DelayMap.union(m1, m2) |> DelayMap.toMap) + + @Test + def union04(): Unit \ Assert = + let m1 = toDelayMap(Map#{}); + let m2 = toDelayMap(Map#{1 => 2, 3 => 4}); + assertEq(expected = Map#{1 => 2, 3 => 4}, DelayMap.union(m1, m2) |> DelayMap.toMap) + + @Test + def union05(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2, 3 => 4}); + let m2 = toDelayMap(Map#{}); + assertEq(expected = Map#{1 => 2, 3 => 4}, DelayMap.union(m1, m2) |> DelayMap.toMap) + + @Test + def union06(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2}); + let m2 = toDelayMap(Map#{3 => 4}); + assertEq(expected = Map#{1 => 2, 3 => 4}, DelayMap.union(m1, m2) |> DelayMap.toMap) + + @Test + def union07(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2}); + let m2 = toDelayMap(Map#{1 => 5}); + assertEq(expected = Map#{1 => 2}, DelayMap.union(m1, m2) |> DelayMap.toMap) + + @Test + def union08(): Unit \ Assert = + let m1 = toDelayMap(Map#{}); + let m2 = toDelayMap(Map#{1 => 2, 2 => 3, 3 => 4}); + assertEq(expected = Map#{1 => 2, 2 => 3, 3 => 4}, DelayMap.union(m1, m2) |> DelayMap.toMap) + + @Test + def union09(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2, 2 => 3, 3 => 4}); + let m2 = toDelayMap(Map#{}); + assertEq(expected = Map#{1 => 2, 2 => 3, 3 => 4}, DelayMap.union(m1, m2) |> DelayMap.toMap) + + @Test + def union10(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2, 2 => 3}); + let m2 = toDelayMap(Map#{3 => 4}); + assertEq(expected = Map#{1 => 2, 2 => 3, 3 => 4}, DelayMap.union(m1, m2) |> DelayMap.toMap) + + @Test + def union11(): Unit \ Assert = + let m1 = toDelayMap(Map#{3 => 4}); + let m2 = toDelayMap(Map#{1 => 2, 2 => 3}); + assertEq(expected = Map#{1 => 2, 2 => 3, 3 => 4}, DelayMap.union(m1, m2) |> DelayMap.toMap) + + @Test + def union12(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2, 2 => 3}); + let m2 = toDelayMap(Map#{2 => 8}); + assertEq(expected = Map#{1 => 2, 2 => 3}, DelayMap.union(m1, m2) |> DelayMap.toMap) + + @Test + def union13(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2, 2 => 3}); + let m2 = toDelayMap(Map#{1 => 8}); + assertEq(expected = Map#{1 => 2, 2 => 3}, DelayMap.union(m1, m2) |> DelayMap.toMap) + + @Test + def union14(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 4}); + let m2 = toDelayMap(Map#{1 => 2, 2 => 3}); + assertEq(expected = Map#{1 => 4, 2 => 3}, DelayMap.union(m1, m2) |> DelayMap.toMap) + + @Test + def union15(): Unit \ Assert = + let m1 = toDelayMap(Map#{2 => 7}); + let m2 = toDelayMap(Map#{1 => 2, 2 => 3}); + assertEq(expected = Map#{1 => 2, 2 => 7}, DelayMap.union(m1, m2) |> DelayMap.toMap) + + @Test + def union16(): Unit \ Assert = + let m1 = toDelayMap(Map#{2 => 7, 11 => 14, 9 => 8, 15 => 22}); + let m2 = toDelayMap(Map#{15 => 21, 1 => 2, 2 => 8, 44 => 33}); + assertEq(expected = Map#{2 => 7, 11 => 14, 9 => 8, 15 => 22, 1 => 2, 44 => 33}, DelayMap.union(m1, m2) |> DelayMap.toMap) + + + ///////////////////////////////////////////////////////////////////////////// + // unionWith // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def unionWith01(): Unit \ Assert = + let m1 = toDelayMap(Map#{}); + let m2 = toDelayMap(Map#{}); + assertEq(expected = (Map#{}: Map[Unit, Int32]), DelayMap.unionWith((v1, v2) -> v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWith02(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2}); + let m2 = toDelayMap(Map#{}); + assertEq(expected = Map#{1 => 2}, DelayMap.unionWith((v1, v2) -> v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWith03(): Unit \ Assert = + let m1 = toDelayMap(Map#{}); + let m2 = toDelayMap(Map#{1 => 2}); + assertEq(expected = Map#{1 => 2}, DelayMap.unionWith((v1, v2) -> v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWith04(): Unit \ Assert = + let m1 = toDelayMap(Map#{}); + let m2 = toDelayMap(Map#{1 => 2, 3 => 4}); + assertEq(expected = Map#{1 => 2, 3 => 4}, DelayMap.unionWith((v1, v2) -> v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWith05(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2, 3 => 4}); + let m2 = toDelayMap(Map#{}); + assertEq(expected = Map#{1 => 2, 3 => 4}, DelayMap.unionWith((v1, v2) -> v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWith06(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2}); + let m2 = toDelayMap(Map#{3 => 4}); + assertEq(expected = Map#{1 => 2, 3 => 4}, DelayMap.unionWith((v1, v2) -> v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWith07(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2}); + let m2 = toDelayMap(Map#{1 => 5}); + assertEq(expected = Map#{1 => -3}, DelayMap.unionWith((v1, v2) -> v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWith08(): Unit \ Assert = + let m1 = toDelayMap(Map#{}); + let m2 = toDelayMap(Map#{1 => 2, 2 => 3, 3 => 4}); + assertEq(expected = Map#{1 => 2, 2 => 3, 3 => 4}, DelayMap.unionWith((v1, v2) -> v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWith09(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2, 2 => 3, 3 => 4}); + let m2 = toDelayMap(Map#{}); + assertEq(expected = Map#{1 => 2, 2 => 3, 3 => 4}, DelayMap.unionWith((v1, v2) -> v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWith10(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2, 2 => 3}); + let m2 = toDelayMap(Map#{3 => 4}); + assertEq(expected = Map#{1 => 2, 2 => 3, 3 => 4}, DelayMap.unionWith((v1, v2) -> v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWith11(): Unit \ Assert = + let m1 = toDelayMap(Map#{3 => 4}); + let m2 = toDelayMap(Map#{1 => 2, 2 => 3}); + assertEq(expected = Map#{1 => 2, 2 => 3, 3 => 4}, DelayMap.unionWith((v1, v2) -> v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWith12(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2, 2 => 3}); + let m2 = toDelayMap(Map#{2 => 8}); + assertEq(expected = Map#{1 => 2, 2 => -5}, DelayMap.unionWith((v1, v2) -> v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWith13(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2, 2 => 3}); + let m2 = toDelayMap(Map#{1 => 8}); + assertEq(expected = Map#{1 => -6, 2 => 3}, DelayMap.unionWith((v1, v2) -> v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWith14(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 4}); + let m2 = toDelayMap(Map#{1 => 2, 2 => 3}); + assertEq(expected = Map#{1 => 2, 2 => 3}, DelayMap.unionWith((v1, v2) -> v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWith15(): Unit \ Assert = + let m1 = toDelayMap(Map#{2 => 7}); + let m2 = toDelayMap(Map#{1 => 2, 2 => 3}); + assertEq(expected = Map#{1 => 2, 2 => 4}, DelayMap.unionWith((v1, v2) -> v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWith16(): Unit \ Assert = + let m1 = toDelayMap(Map#{2 => 7, 11 => 14, 9 => 8, 15 => 22}); + let m2 = toDelayMap(Map#{15 => 21, 1 => 2, 2 => 8, 44 => 33}); + assertEq(expected = Map#{2 => -1, 11 => 14, 9 => 8, 15 => 1, 1 => 2, 44 => 33}, DelayMap.unionWith((v1, v2) -> v1 - v2, m1, m2) |> DelayMap.toMap) + + + ///////////////////////////////////////////////////////////////////////////// + // unionWithKey (pure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def unionWithKeyPure01(): Unit \ Assert = + let m1 = toDelayMap(Map#{}); + let m2 = toDelayMap(Map#{}); + assertEq(expected = (Map#{}: Map[Int32, Int32]), DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyPure02(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2}); + let m2 = toDelayMap(Map#{}); + assertEq(expected = Map#{1 => 2}, DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyPure03(): Unit \ Assert = + let m1 = toDelayMap(Map#{}); + let m2 = toDelayMap(Map#{1 => 2}); + assertEq(expected = Map#{1 => 2}, DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyPure04(): Unit \ Assert = + let m1 = toDelayMap(Map#{}); + let m2 = toDelayMap(Map#{1 => 2, 3 => 4}); + assertEq(expected = Map#{1 => 2, 3 => 4}, DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyPure05(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2, 3 => 4}); + let m2 = toDelayMap(Map#{}); + assertEq(expected = Map#{1 => 2, 3 => 4}, DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyPure06(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2}); + let m2 = toDelayMap(Map#{3 => 4}); + assertEq(expected = Map#{1 => 2, 3 => 4}, DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyPure07(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2}); + let m2 = toDelayMap(Map#{1 => 5}); + assertEq(expected = Map#{1 => -2}, DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyPure08(): Unit \ Assert = + let m1 = toDelayMap(Map#{}); + let m2 = toDelayMap(Map#{1 => 2, 2 => 3, 3 => 4}); + assertEq(expected = Map#{1 => 2, 2 => 3, 3 => 4}, DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyPure09(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2, 2 => 3, 3 => 4}); + let m2 = toDelayMap(Map#{}); + assertEq(expected = Map#{1 => 2, 2 => 3, 3 => 4}, DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyPure10(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2, 2 => 3}); + let m2 = toDelayMap(Map#{3 => 4}); + assertEq(expected = Map#{1 => 2, 2 => 3, 3 => 4}, DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyPure11(): Unit \ Assert = + let m1 = toDelayMap(Map#{3 => 4}); + let m2 = toDelayMap(Map#{1 => 2, 2 => 3}); + assertEq(expected = Map#{1 => 2, 2 => 3, 3 => 4}, DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyPure12(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2, 2 => 3}); + let m2 = toDelayMap(Map#{2 => 8}); + assertEq(expected = Map#{1 => 2, 2 => -3}, DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyPure13(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 2, 2 => 3}); + let m2 = toDelayMap(Map#{1 => 8}); + assertEq(expected = Map#{1 => -5, 2 => 3}, DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyPure14(): Unit \ Assert = + let m1 = toDelayMap(Map#{1 => 4}); + let m2 = toDelayMap(Map#{1 => 2, 2 => 3}); + assertEq(expected = Map#{1 => 3, 2 => 3}, DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyPure15(): Unit \ Assert = + let m1 = toDelayMap(Map#{2 => 7}); + let m2 = toDelayMap(Map#{1 => 2, 2 => 3}); + assertEq(expected = Map#{1 => 2, 2 => 6}, DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyPure16(): Unit \ Assert = + let m1 = toDelayMap(Map#{2 => 7, 11 => 14, 9 => 8, 15 => 22}); + let m2 = toDelayMap(Map#{15 => 21, 1 => 2, 2 => 8, 44 => 33}); + assertEq(expected = Map#{2 => 1, 11 => 14, 9 => 8, 15 => 16, 1 => 2, 44 => 33}, DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, m1, m2) |> DelayMap.toMap) + + + ///////////////////////////////////////////////////////////////////////////// + // unionWithKey (impure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def unionWithKeyImpure01(): Unit \ {Assert, IO} = + let m1 = toDelayMap(Map#{}); + let m2 = toDelayMap(Map#{}); + assertEq(expected = (Map#{}: Map[Int32, Int32]), DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyImpure02(): Unit \ {Assert, IO} = + let m1 = toDelayMap(Map#{1 => 2}); + let m2 = toDelayMap(Map#{}); + assertEq(expected = Map#{1 => 2}, DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyImpure03(): Unit \ {Assert, IO} = + let m1 = toDelayMap(Map#{}); + let m2 = toDelayMap(Map#{1 => 2}); + assertEq(expected = Map#{1 => 2}, DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyImpure04(): Unit \ {Assert, IO} = + let m1 = toDelayMap(Map#{}); + let m2 = toDelayMap(Map#{1 => 2, 3 => 4}); + assertEq(expected = Map#{1 => 2, 3 => 4}, DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyImpure05(): Unit \ {Assert, IO} = + let m1 = toDelayMap(Map#{1 => 2, 3 => 4}); + let m2 = toDelayMap(Map#{}); + assertEq(expected = Map#{1 => 2, 3 => 4}, DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyImpure06(): Unit \ {Assert, IO} = + let m1 = toDelayMap(Map#{1 => 2}); + let m2 = toDelayMap(Map#{3 => 4}); + assertEq(expected = Map#{1 => 2, 3 => 4}, DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyImpure07(): Unit \ {Assert, IO} = + let m1 = toDelayMap(Map#{1 => 2}); + let m2 = toDelayMap(Map#{1 => 5}); + assertEq(expected = Map#{1 => -2}, DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyImpure08(): Unit \ {Assert, IO} = + let m1 = toDelayMap(Map#{}); + let m2 = toDelayMap(Map#{1 => 2, 2 => 3, 3 => 4}); + assertEq(expected = Map#{1 => 2, 2 => 3, 3 => 4}, DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyImpure09(): Unit \ {Assert, IO} = + let m1 = toDelayMap(Map#{1 => 2, 2 => 3, 3 => 4}); + let m2 = toDelayMap(Map#{}); + assertEq(expected = Map#{1 => 2, 2 => 3, 3 => 4}, DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyImpure10(): Unit \ {Assert, IO} = + let m1 = toDelayMap(Map#{1 => 2, 2 => 3}); + let m2 = toDelayMap(Map#{3 => 4}); + assertEq(expected = Map#{1 => 2, 2 => 3, 3 => 4}, DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyImpure11(): Unit \ {Assert, IO} = + let m1 = toDelayMap(Map#{3 => 4}); + let m2 = toDelayMap(Map#{1 => 2, 2 => 3}); + assertEq(expected = Map#{1 => 2, 2 => 3, 3 => 4}, DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyImpure12(): Unit \ {Assert, IO} = + let m1 = toDelayMap(Map#{1 => 2, 2 => 3}); + let m2 = toDelayMap(Map#{2 => 8}); + assertEq(expected = Map#{1 => 2, 2 => -3}, DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyImpure13(): Unit \ {Assert, IO} = + let m1 = toDelayMap(Map#{1 => 2, 2 => 3}); + let m2 = toDelayMap(Map#{1 => 8}); + assertEq(expected = Map#{1 => -5, 2 => 3}, DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyImpure14(): Unit \ {Assert, IO} = + let m1 = toDelayMap(Map#{1 => 4}); + let m2 = toDelayMap(Map#{1 => 2, 2 => 3}); + assertEq(expected = Map#{1 => 3, 2 => 3}, DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyImpure15(): Unit \ {Assert, IO} = + let m1 = toDelayMap(Map#{2 => 7}); + let m2 = toDelayMap(Map#{1 => 2, 2 => 3}); + assertEq(expected = Map#{1 => 2, 2 => 6}, DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), m1, m2) |> DelayMap.toMap) + + @Test + def unionWithKeyImpure16(): Unit \ {Assert, IO} = + let m1 = toDelayMap(Map#{2 => 7, 11 => 14, 9 => 8, 15 => 22}); + let m2 = toDelayMap(Map#{15 => 21, 1 => 2, 2 => 8, 44 => 33}); + assertEq(expected = Map#{2 => 1, 11 => 14, 9 => 8, 15 => 16, 1 => 2, 44 => 33}, DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), m1, m2) |> DelayMap.toMap) + + + ///////////////////////////////////////////////////////////////////////////// + // unionWithKey unionWithKey // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def unionWithKeyUnionWithKey01(): Unit \ Assert = + assertEq(expected = Map#{1 => 6}, toDelayMap(Map#{1 => 5}) |> + DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, toDelayMap(Map#{1 => 2})) |> + DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, toDelayMap(Map#{1 => 3})) |> + DelayMap.toMap) + + @Test + def unionWithKeyUnionWithKey02(): Unit \ {Assert, IO} = + assertEq(expected = Map#{1 => 6}, toDelayMap(Map#{1 => 5}) |> + DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), toDelayMap(Map#{1 => 2})) |> + DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, toDelayMap(Map#{1 => 3})) |> + DelayMap.toMap) + + @Test + def unionWithKeyUnionWithKey03(): Unit \ {Assert, IO} = + assertEq(expected = Map#{1 => 6}, toDelayMap(Map#{1 => 5}) |> + DelayMap.unionWithKey((k, v1, v2) -> k + v1 - v2, toDelayMap(Map#{1 => 2})) |> + DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), toDelayMap(Map#{1 => 3})) |> + DelayMap.toMap) + + @Test + def unionWithKeyUnionWithKey04(): Unit \ {Assert, IO} = + assertEq(expected = Map#{1 => 6}, toDelayMap(Map#{1 => 5}) |> + DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), toDelayMap(Map#{1 => 2})) |> + DelayMap.unionWithKey((k, v1, v2) -> unchecked_cast(k + v1 - v2 as _ \ IO), toDelayMap(Map#{1 => 3})) |> + DelayMap.toMap) + + + ///////////////////////////////////////////////////////////////////////////// + // unionWithKey (fusion) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def unionWithKeyFusion01(): Unit \ Assert = region rc { + let l = Ref.fresh(rc, Nil); + discard Map#{1 => 1, 2 => 2, 3 => 3} |> toDelayMap |> + DelayMap.unionWithKey((_, _, v) -> { Ref.put("a" :: Ref.get(l), l); v }, toDelayMap(Map#{1 => 1, 2 => 2, 3 => 3})) |> + DelayMap.unionWithKey((_, _, v) -> { Ref.put("b" :: Ref.get(l), l); v }, toDelayMap(Map#{1 => 1, 2 => 2, 3 => 3})); + assertEq(expected = ("a" :: "a" :: "a" :: "b" :: "b" :: "b" :: Nil), List.reverse(Ref.get(l))) + } + + ///////////////////////////////////////////////////////////////////////////// + // adjust // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def adjust01(): Unit \ Assert = + let m = toDelayMap(Map#{}); + assertEq(expected = Map#{}, DelayMap.adjust(v -> 2 * v, 1, m) |> DelayMap.toMap) + + @Test + def adjust02(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4}); + assertEq(expected = Map#{1 => 8}, DelayMap.adjust(v -> 2 * v, 1, m) |> DelayMap.toMap) + + @Test + def adjust03(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4}); + assertEq(expected = Map#{1 => 4}, DelayMap.adjust(v -> 2 * v, 2, m) |> DelayMap.toMap) + + @Test + def adjust04(): Unit \ Assert = + let m = toDelayMap(Map#{1 => -14, 5 => -2}); + assertEq(expected = Map#{1 => -28, 5 => -2}, DelayMap.adjust(v -> 2 * v, 1, m) |> DelayMap.toMap) + + @Test + def adjust05(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4, 5 => -2}); + assertEq(expected = Map#{1 => 4, 5 => -4}, DelayMap.adjust(v -> 2 * v, 5, m) |> DelayMap.toMap) + + @Test + def adjust06(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4, 5 => -2}); + assertEq(expected = Map#{1 => 4, 5 => -2}, DelayMap.adjust(v -> 2 * v, 4, m) |> DelayMap.toMap) + + + ///////////////////////////////////////////////////////////////////////////// + // adjustWithKey // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def adjustWithKey01(): Unit \ Assert = + let m = toDelayMap(Map#{}); + assertEq(expected = Map#{}, DelayMap.adjustWithKey((k, v) -> k + v, 1, m) |> DelayMap.toMap) + + @Test + def adjustWithKey02(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4}); + assertEq(expected = Map#{1 => 5}, DelayMap.adjustWithKey((k, v) -> k + v, 1, m) |> DelayMap.toMap) + + @Test + def adjustWithKey03(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4}); + assertEq(expected = Map#{1 => 4}, DelayMap.adjustWithKey((k, v) -> k + v, 2, m) |> DelayMap.toMap) + + @Test + def adjustWithKey04(): Unit \ Assert = + let m = toDelayMap(Map#{1 => -14, 5 => -2}); + assertEq(expected = Map#{1 => -13, 5 => -2}, DelayMap.adjustWithKey((k, v) -> k + v, 1, m) |> DelayMap.toMap) + + @Test + def adjustWithKey05(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4, 5 => -2}); + assertEq(expected = Map#{1 => 4, 5 => 3}, DelayMap.adjustWithKey((k, v) -> k + v, 5, m) |> DelayMap.toMap) + + @Test + def adjustWithKey06(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4, 5 => -2}); + assertEq(expected = Map#{1 => 4, 5 => -2}, DelayMap.adjustWithKey((k, v) -> k + v, 4, m) |> DelayMap.toMap) + + + ///////////////////////////////////////////////////////////////////////////// + // update // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def update01(): Unit \ Assert = + let m = toDelayMap(Map#{}); + assertEq(expected = Map#{}, DelayMap.update(v -> if (v `Int32.remainder` 2 != 0) Some(2 * v) else None, 1, m) |> DelayMap.toMap) + + @Test + def update02(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 3}); + assertEq(expected = Map#{1 => 6}, DelayMap.update(v -> if (v `Int32.remainder` 2 != 0) Some(2 * v) else None, 1, m) |> DelayMap.toMap) + + @Test + def update03(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4}); + assertEq(expected = Map#{1 => 4}, DelayMap.update(v -> if (v `Int32.remainder` 2 != 0) Some(2 * v) else None, 1, m) |> DelayMap.toMap) + + @Test + def update04(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4}); + assertEq(expected = Map#{1 => 4}, DelayMap.update(v -> if (v `Int32.remainder` 2 != 0) Some(2 * v) else None, 2, m) |> DelayMap.toMap) + + @Test + def update05(): Unit \ Assert = + let m = toDelayMap(Map#{1 => -14, 5 => -2}); + assertEq(expected = Map#{1 => -14, 5 => -2}, DelayMap.update(v -> if (v `Int32.remainder` 2 != 0) Some(2 * v) else None, 1, m) |> DelayMap.toMap) + + @Test + def update06(): Unit \ Assert = + let m = toDelayMap(Map#{1 => -13, 5 => -2}); + assertEq(expected = Map#{1 => -26, 5 => -2}, DelayMap.update(v -> if (v `Int32.remainder` 2 != 0) Some(2 * v) else None, 1, m) |> DelayMap.toMap) + + @Test + def update07(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4, 5 => -2}); + assertEq(expected = Map#{1 => 4, 5 => -2}, DelayMap.update(v -> if (v `Int32.remainder` 2 != 0) Some(2 * v) else None, 5, m) |> DelayMap.toMap) + + @Test + def update08(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4, 5 => -1}); + assertEq(expected = Map#{1 => 4, 5 => -2}, DelayMap.update(v -> if (v `Int32.remainder` 2 != 0) Some(2 * v) else None, 5, m) |> DelayMap.toMap) + + @Test + def update09(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4, 5 => -2}); + assertEq(expected = Map#{1 => 4, 5 => -2}, DelayMap.update(v -> if (v `Int32.remainder` 2 != 0) Some(2 * v) else None, 4, m) |> DelayMap.toMap) + + + ///////////////////////////////////////////////////////////////////////////// + // updateWithKey (pure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def updateWithKeyPure01(): Unit \ Assert = + let m = toDelayMap(Map#{}); + assertEq(expected = Map#{}, DelayMap.updateWithKey((k, v) -> if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None, 1, m) |> + DelayMap.toMap) + + @Test + def updateWithKeyPure02(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 3}); + assertEq(expected = Map#{1 => 7}, DelayMap.updateWithKey((k, v) -> if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None, 1, m) |> + DelayMap.toMap) + + @Test + def updateWithKeyPure03(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4}); + assertEq(expected = Map#{1 => 4}, DelayMap.updateWithKey((k, v) -> if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None, 1, m) |> + DelayMap.toMap) + + @Test + def updateWithKeyPure04(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4}); + assertEq(expected = Map#{1 => 4}, DelayMap.updateWithKey((k, v) -> if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None, 2, m) |> + DelayMap.toMap) + + @Test + def updateWithKeyPure05(): Unit \ Assert = + let m = toDelayMap(Map#{1 => -14, 5 => -2}); + assertEq(expected = Map#{1 => -14, 5 => -2}, DelayMap.updateWithKey((k, v) -> if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None, 1, m) |> + DelayMap.toMap) + + @Test + def updateWithKeyPure06(): Unit \ Assert = + let m = toDelayMap(Map#{1 => -13, 5 => -2}); + assertEq(expected = Map#{1 => -25, 5 => -2}, DelayMap.updateWithKey((k, v) -> if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None, 1, m) |> + DelayMap.toMap) + + @Test + def updateWithKeyPure07(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4, 5 => -2}); + assertEq(expected = Map#{1 => 4, 5 => -2}, DelayMap.updateWithKey((k, v) -> if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None, 5, m) |> + DelayMap.toMap) + + @Test + def updateWithKeyPure08(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4, 5 => -1}); + assertEq(expected = Map#{1 => 4, 5 => 3}, DelayMap.updateWithKey((k, v) -> if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None, 5, m) |> + DelayMap.toMap) + + @Test + def updateWithKeyPure09(): Unit \ Assert = + let m = toDelayMap(Map#{1 => 4, 5 => -2}); + assertEq(expected = Map#{1 => 4, 5 => -2}, DelayMap.updateWithKey((k, v) -> if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None, 4, m) |> + DelayMap.toMap) + + + ///////////////////////////////////////////////////////////////////////////// + // updateWithKey (pure) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def updateWithKeyImpure01(): Unit \ {Assert, IO} = + let m = toDelayMap(Map#{}); + assertEq(expected = Map#{}, DelayMap.updateWithKey((k, v) -> unchecked_cast(if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None as _ \ IO), 1, m) |> + DelayMap.toMap) + + @Test + def updateWithKeyImpure02(): Unit \ {Assert, IO} = + let m = toDelayMap(Map#{1 => 3}); + assertEq(expected = Map#{1 => 7}, DelayMap.updateWithKey((k, v) -> unchecked_cast(if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None as _ \ IO), 1, m) |> + DelayMap.toMap) + + @Test + def updateWithKeyImpure03(): Unit \ {Assert, IO} = + let m = toDelayMap(Map#{1 => 4}); + assertEq(expected = Map#{1 => 4}, DelayMap.updateWithKey((k, v) -> unchecked_cast(if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None as _ \ IO), 1, m) |> + DelayMap.toMap) + + @Test + def updateWithKeyImpure04(): Unit \ {Assert, IO} = + let m = toDelayMap(Map#{1 => 4}); + assertEq(expected = Map#{1 => 4}, DelayMap.updateWithKey((k, v) -> unchecked_cast(if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None as _ \ IO), 2, m) |> + DelayMap.toMap) + + @Test + def updateWithKeyImpure05(): Unit \ {Assert, IO} = + let m = toDelayMap(Map#{1 => -14, 5 => -2}); + assertEq(expected = Map#{1 => -14, 5 => -2}, DelayMap.updateWithKey((k, v) -> unchecked_cast(if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None as _ \ IO), 1, m) |> + DelayMap.toMap) + + @Test + def updateWithKeyImpure06(): Unit \ {Assert, IO} = + let m = toDelayMap(Map#{1 => -13, 5 => -2}); + assertEq(expected = Map#{1 => -25, 5 => -2}, DelayMap.updateWithKey((k, v) -> unchecked_cast(if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None as _ \ IO), 1, m) |> + DelayMap.toMap) + + @Test + def updateWithKeyImpure07(): Unit \ {Assert, IO} = + let m = toDelayMap(Map#{1 => 4, 5 => -2}); + assertEq(expected = Map#{1 => 4, 5 => -2}, DelayMap.updateWithKey((k, v) -> unchecked_cast(if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None as _ \ IO), 5, m) |> + DelayMap.toMap) + + @Test + def updateWithKeyImpure08(): Unit \ {Assert, IO} = + let m = toDelayMap(Map#{1 => 4, 5 => -1}); + assertEq(expected = Map#{1 => 4, 5 => 3}, DelayMap.updateWithKey((k, v) -> unchecked_cast(if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None as _ \ IO), 5, m) |> + DelayMap.toMap) + + @Test + def updateWithKeyImpure09(): Unit \ {Assert, IO} = + let m = toDelayMap(Map#{1 => 4, 5 => -2}); + assertEq(expected = Map#{1 => 4, 5 => -2}, DelayMap.updateWithKey((k, v) -> unchecked_cast(if (v `Int32.remainder` 2 != 0) Some(k + 2 * v) else None as _ \ IO), 4, m) |> + DelayMap.toMap) + + + ///////////////////////////////////////////////////////////////////////////// + // updateWithKey updateWithKey // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def updateWithKeyUpdateWithKey01(): Unit \ Assert = + assertEq(expected = Map#{1 => 9, 5 => 1}, toDelayMap(Map#{1 => 4, 5 => -2}) |> + DelayMap.updateWithKey((k, v) -> if (v == 4) Some(k + 2 * v) else None, 1) |> + DelayMap.updateWithKey((k, v) -> if (k == 5) Some(k + 2 * v) else None, 5) |> + DelayMap.toMap) + + @Test + def updateWithKeyUpdateWithKey02(): Unit \ {Assert, IO} = + assertEq(expected = Map#{1 => 9, 5 => 1}, toDelayMap(Map#{1 => 4, 5 => -2}) |> + DelayMap.updateWithKey((k, v) -> unchecked_cast(if (v == 4) Some(k + 2 * v) else None as _ \ IO), 1) |> + DelayMap.updateWithKey((k, v) -> if (k == 5) Some(k + 2 * v) else None, 5) |> + DelayMap.toMap) + + @Test + def updateWithKeyUpdateWithKey03(): Unit \ {Assert, IO} = + assertEq(expected = Map#{1 => 9, 5 => 1}, toDelayMap(Map#{1 => 4, 5 => -2}) |> + DelayMap.updateWithKey((k, v) -> if (v == 4) Some(k + 2 * v) else None, 1) |> + DelayMap.updateWithKey((k, v) -> unchecked_cast(if (k == 5) Some(k + 2 * v) else None as _ \ IO), 5) |> + DelayMap.toMap) + + @Test + def updateWithKeyUpdateWithKey04(): Unit \ {Assert, IO} = + assertEq(expected = Map#{1 => 9, 5 => 1}, toDelayMap(Map#{1 => 4, 5 => -2}) |> + DelayMap.updateWithKey((k, v) -> unchecked_cast(if (v == 4) Some(k + 2 * v) else None as _ \ IO), 1) |> + DelayMap.updateWithKey((k, v) -> unchecked_cast(if (k == 5) Some(k + 2 * v) else None as _ \ IO), 5) |> + DelayMap.toMap) + + + ///////////////////////////////////////////////////////////////////////////// + // updateWithKey (fusion) // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def updateWithKeyFusion01(): Unit \ Assert = region rc { + let l = Ref.fresh(rc, Nil); + discard toDelayMap(Map#{1 => 1, 2 => 2, 3 => 3}) |> + DelayMap.updateWithKey((_, v) -> { Ref.put("a" :: Ref.get(l), l); Some(v) }, 1) |> + DelayMap.updateWithKey((_, v) -> { Ref.put("a" :: Ref.get(l), l); Some(v) }, 2) |> + DelayMap.updateWithKey((_, v) -> { Ref.put("a" :: Ref.get(l), l); Some(v) }, 3) |> + DelayMap.updateWithKey((_, v) -> { Ref.put("b" :: Ref.get(l), l); Some(v) }, 1) |> + DelayMap.updateWithKey((_, v) -> { Ref.put("b" :: Ref.get(l), l); Some(v) }, 2) |> + DelayMap.updateWithKey((_, v) -> { Ref.put("b" :: Ref.get(l), l); Some(v) }, 3); + assertEq(expected = "a" :: "a" :: "a" :: "b" :: "b" :: "b" :: Nil, List.reverse(Ref.get(l))) + } + + ///////////////////////////////////////////////////////////////////////////// + // size // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def size01(): Unit \ Assert = + assertEq(expected = 0, Map#{} |> toDelayMap |> DelayMap.size) + + @Test + def size02(): Unit \ Assert = + assertEq(expected = 1, Map#{1 => 2} |> toDelayMap |> DelayMap.size) + + @Test + def size03(): Unit \ Assert = + assertEq(expected = 2, Map#{1 => 2, 2 => 4} |> toDelayMap |> DelayMap.size) + + @Test + def size04(): Unit \ Assert = + assertEq(expected = 3, Map#{1 => 2, 2 => 4, 3 => 6} |> toDelayMap |> DelayMap.size) + + @Test + def size05(): Unit \ Assert = + assertEq(expected = 4, Map#{1 => 2, 2 => 4, 3 => 6, 4 => 8} |> toDelayMap |> DelayMap.size) + + @Test + def size06(): Unit \ Assert = + assertEq(expected = 5, Map#{1 => 2, 2 => 4, 3 => 6, 4 => 8, 5 => 10} |> toDelayMap |> DelayMap.size) + + + ///////////////////////////////////////////////////////////////////////////// + // singleton // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def singleton01(): Unit \ Assert = + assertEq(expected = Map#{1 => 2}, DelayMap.singleton(1, 2) |> DelayMap.toMap) + + @Test + def singleton02(): Unit \ Assert = + assertEq(expected = Map#{3 => -1}, DelayMap.singleton(3, -1) |> DelayMap.toMap) + + @Test + def singleton03(): Unit \ Assert = + assertEq(expected = Map#{-99 => -11}, DelayMap.singleton(-99, -11) |> DelayMap.toMap) + + + ///////////////////////////////////////////////////////////////////////////// + // isEmpty // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def isEmpty01(): Unit \ Assert = + assertTrue((Map#{}: Map[Unit, Unit]) |> toDelayMap |> DelayMap.isEmpty) + + @Test + def isEmpty02(): Unit \ Assert = + assertTrue(not (Map#{1 => 2} |> toDelayMap |> DelayMap.isEmpty)) + + @Test + def isEmpty03(): Unit \ Assert = + assertTrue(not (Map#{1 => 2, 2 => 4} |> toDelayMap |> DelayMap.isEmpty)) + + @Test + def isEmpty04(): Unit \ Assert = + assertTrue(not (Map#{1 => 2, 2 => 4, 3 => 6} |> toDelayMap |> DelayMap.isEmpty)) + + @Test + def isEmpty05(): Unit \ Assert = + assertTrue(not (Map#{1 => 2, 2 => 4, 3 => 6, 4 => 8} |> toDelayMap |> DelayMap.isEmpty)) + + + ///////////////////////////////////////////////////////////////////////////// + // nonEmpty // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def nonEmpty01(): Unit \ Assert = + assertTrue(not ((Map#{}: Map[Unit, Unit]) |> toDelayMap |> DelayMap.nonEmpty)) + + @Test + def nonEmpty02(): Unit \ Assert = + assertTrue(Map#{1 => 2} |> toDelayMap |> DelayMap.nonEmpty) + + @Test + def nonEmpty03(): Unit \ Assert = + assertTrue(Map#{1 => 2, 2 => 4} |> toDelayMap |> DelayMap.nonEmpty) + + @Test + def nonEmpty04(): Unit \ Assert = + assertTrue(Map#{1 => 2, 2 => 4, 3 => 6} |> toDelayMap |> DelayMap.nonEmpty) + + @Test + def nonEmpty05(): Unit \ Assert = + assertTrue(Map#{1 => 2, 2 => 4, 3 => 6, 4 => 8} |> toDelayMap |> DelayMap.nonEmpty) + + + ///////////////////////////////////////////////////////////////////////////// + // foldLeft // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def foldLeft01(): Unit \ Assert = + assertEq(expected = 0, Map#{} |> toDelayMap |> + DelayMap.foldLeft((s, v) -> s + v, 0)) + + @Test + def foldLeft02(): Unit \ Assert = + assertEq(expected = 2, Map#{1 => 2} |> toDelayMap |> + DelayMap.foldLeft((s, v) -> s + v, 0)) + + @Test + def foldLeft03(): Unit \ Assert = + assertEq(expected = 6, Map#{1 => 2, 3 => 4} |> toDelayMap |> + DelayMap.foldLeft((s, v) -> s + v, 0)) + + @Test + def foldLeft04(): Unit \ Assert = + assertEq(expected = 12, Map#{1 => 2, 3 => 4, 5 => 6} |> toDelayMap |> + DelayMap.foldLeft((s, v) -> s + v, 0)) + + + ///////////////////////////////////////////////////////////////////////////// + // foldLeftWithKey // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def foldLeftWithKey01(): Unit \ Assert = + assertEq(expected = 0, Map#{} |> toDelayMap |> + DelayMap.foldLeftWithKey((s, k, v) -> k + s + v, 0)) + + @Test + def foldLeftWithKey02(): Unit \ Assert = + assertEq(expected = 3, Map#{1 => 2} |> toDelayMap |> + DelayMap.foldLeftWithKey((s, k, v) -> k + s + v, 0)) + + @Test + def foldLeftWithKey03(): Unit \ Assert = + assertEq(expected = 10, Map#{1 => 2, 3 => 4} |> toDelayMap |> + DelayMap.foldLeftWithKey((s, k, v) -> k + s + v, 0)) + + @Test + def foldLeftWithKey04(): Unit \ Assert = + assertEq(expected = 21, Map#{1 => 2, 3 => 4, 5 => 6} |> toDelayMap |> + DelayMap.foldLeftWithKey((s, k, v) -> k + s + v, 0)) + + + ///////////////////////////////////////////////////////////////////////////// + // foldRight // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def foldRight01(): Unit \ Assert = + assertEq(expected = 0, Map#{} |> toDelayMap |> + DelayMap.foldRight((v, acc) -> acc + v, 0)) + + @Test + def foldRight02(): Unit \ Assert = + assertEq(expected = 2, Map#{1 => 2} |> toDelayMap |> + DelayMap.foldRight((v, acc) -> acc + v, 0)) + + @Test + def foldRight03(): Unit \ Assert = + assertEq(expected = 6, Map#{1 => 2, 3 => 4} |> toDelayMap |> + DelayMap.foldRight((v, acc) -> acc + v, 0)) + + @Test + def foldRight04(): Unit \ Assert = + assertEq(expected = 12, Map#{1 => 2, 3 => 4, 5 => 6} |> toDelayMap |> + DelayMap.foldRight((v, acc) -> acc + v, 0)) + + + ///////////////////////////////////////////////////////////////////////////// + // foldRightWithKey // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def foldRightWithKey01(): Unit \ Assert = + assertEq(expected = 0, Map#{} |> toDelayMap |> + DelayMap.foldRightWithKey((k, v, acc) -> k + acc + v, 0)) + + @Test + def foldRightWithKey02(): Unit \ Assert = + assertEq(expected = 3, Map#{1 => 2} |> toDelayMap |> + DelayMap.foldRightWithKey((k, v, acc) -> k + acc + v, 0)) + + @Test + def foldRightWithKey03(): Unit \ Assert = + assertEq(expected = 10, Map#{1 => 2, 3 => 4} |> toDelayMap |> + DelayMap.foldRightWithKey((k, v, acc) -> k + acc + v, 0)) + + @Test + def foldRightWithKey04(): Unit \ Assert = + assertEq(expected = 21, Map#{1 => 2, 3 => 4, 5 => 6} |> toDelayMap |> + DelayMap.foldRightWithKey((k, v, acc) -> k + acc + v, 0)) + + ///////////////////////////////////////////////////////////////////////////// + // reduceLeft // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def reduceLeft01(): Unit \ Assert = + assertEq(expected = None, (Map#{}: Map[Unit, Int32]) |> toDelayMap |> + DelayMap.reduceLeft((v1, v2) -> v1 - v2)) + + @Test + def reduceLeft02(): Unit \ Assert = + assertEq(expected = Some(2), Map#{1 => 2} |> toDelayMap |> + DelayMap.reduceLeft((v1, v2) -> v1 - v2)) + + @Test + def reduceLeft03(): Unit \ Assert = + assertEq(expected = Some(-1), Map#{1 => 2, 2 => 3} |> toDelayMap |> + DelayMap.reduceLeft((v1, v2) -> v1 - v2)) + + @Test + def reduceLeft04(): Unit \ Assert = + assertEq(expected = Some(-5), Map#{1 => 2, 2 => 3, 3 => 4} |> toDelayMap |> + DelayMap.reduceLeft((v1, v2) -> v1 - v2)) + + + ///////////////////////////////////////////////////////////////////////////// + // reduceLeftWithKey // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def reduceLeftWithKey01(): Unit \ Assert = + assertEq(expected = None, (Map#{}: Map[Int32, Int32]) |> toDelayMap |> + DelayMap.reduceLeftWithKey((k1, v1, k2, v2) -> (k1 - k2, v1 - v2))) + + @Test + def reduceLeftWithKey02(): Unit \ Assert = + assertEq(expected = Some((1, 2)), Map#{1 => 2} |> toDelayMap |> + DelayMap.reduceLeftWithKey((k1, v1, k2, v2) -> (k1 - k2, v1 - v2))) + + @Test + def reduceLeftWithKey03(): Unit \ Assert = + assertEq(expected = Some((-1, -1)), Map#{1 => 2, 2 => 3} |> toDelayMap |> + DelayMap.reduceLeftWithKey((k1, v1, k2, v2) -> (k1 - k2, v1 - v2))) + + @Test + def reduceLeftWithKey04(): Unit \ Assert = + assertEq(expected = Some((-4, -5)), Map#{1 => 2, 2 => 3, 3 => 4} |> toDelayMap |> + DelayMap.reduceLeftWithKey((k1, v1, k2, v2) -> (k1 - k2, v1 - v2))) + + + ///////////////////////////////////////////////////////////////////////////// + // reduceRight // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def reduceRight01(): Unit \ Assert = + assertEq(expected = None, (Map#{}: Map[Unit, Int32]) |> toDelayMap |> + DelayMap.reduceRight((v1, v2) -> v1 - v2)) + + @Test + def reduceRight02(): Unit \ Assert = + assertEq(expected = Some(2), Map#{1 => 2} |> toDelayMap |> + DelayMap.reduceRight((v1, v2) -> v1 - v2)) + + @Test + def reduceRight03(): Unit \ Assert = + assertEq(expected = Some(-1), Map#{1 => 2, 2 => 3} |> toDelayMap |> + DelayMap.reduceRight((v1, v2) -> v1 - v2)) + + @Test + def reduceRight04(): Unit \ Assert = + assertEq(expected = Some(3), Map#{1 => 2, 2 => 3, 3 => 4} |> toDelayMap |> + DelayMap.reduceRight((v1, v2) -> v1 - v2)) + + + ///////////////////////////////////////////////////////////////////////////// + // reduceRightWithKey // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def reduceRightWithKey01(): Unit \ Assert = + assertEq(expected = None, (Map#{}: Map[Int32, Int32]) |> toDelayMap |> + DelayMap.reduceRightWithKey((k1, v1, k2, v2) -> (k1 - k2, v1 - v2))) + + @Test + def reduceRightWithKey02(): Unit \ Assert = + assertEq(expected = Some((1, 2)), Map#{1 => 2} |> toDelayMap |> + DelayMap.reduceRightWithKey((k1, v1, k2, v2) -> (k1 - k2, v1 - v2))) + + @Test + def reduceRightWithKey03(): Unit \ Assert = + assertEq(expected = Some((-1, -1)), Map#{1 => 2, 2 => 3} |> toDelayMap |> + DelayMap.reduceRightWithKey((k1, v1, k2, v2) -> (k1 - k2, v1 - v2))) + + @Test + def reduceRightWithKey04(): Unit \ Assert = + assertEq(expected = Some((2 , 3)), Map#{1 => 2, 2 => 3, 3 => 4} |> toDelayMap |> + DelayMap.reduceRightWithKey((k1, v1, k2, v2) -> (k1 - k2, v1 - v2))) + + + ///////////////////////////////////////////////////////////////////////////// + // forEach // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def forEach01(): Unit \ Assert = region rc { + let ri = Ref.fresh(rc, 21); + Map#{} |> toDelayMap |> + DelayMap.forEach((k, _) -> Ref.put(k, ri)); + assertEq(expected = 21, Ref.get(ri)) + } + + @Test + def forEach02(): Unit \ Assert = region rc { + let ri = Ref.fresh(rc, 21); + Map#{1 => "Hello World!"} |> toDelayMap |> + DelayMap.forEach((k, _) -> Ref.put(k, ri)); + assertEq(expected = 1, Ref.get(ri)) + } + + ///////////////////////////////////////////////////////////////////////////// + // forEach // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def forEachWithIndex01(): Unit \ Assert = region rc { + let ri = Ref.fresh(rc, 21); + Map#{} |> toDelayMap |> + DelayMap.forEachWithIndex((i, _, _) -> Ref.put(i, ri)); + assertEq(expected = 21, Ref.get(ri)) + } + + @Test + def forEachWithIndex02(): Unit \ Assert = region rc { + let ri = Ref.fresh(rc, 21); + Map#{1 => "Hello World!"} |> toDelayMap |> + DelayMap.forEachWithIndex((i, _, _) -> Ref.put(i, ri)); + assertEq(expected = 0, Ref.get(ri)) + } + + ///////////////////////////////////////////////////////////////////////////// + // memberOf // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def memberOf01(): Unit \ Assert = + assertTrue(not ((Map#{}: Map[_, Unit]) |> toDelayMap |> + DelayMap.memberOf(2))) + + @Test + def memberOf02(): Unit \ Assert = + assertTrue(not (Map#{1 => 2} |> toDelayMap |> + DelayMap.memberOf(2))) + + @Test + def memberOf03(): Unit \ Assert = + assertTrue(Map#{2 => 1} |> toDelayMap |> + DelayMap.memberOf(2)) + + @Test + def memberOf04(): Unit \ Assert = + assertTrue(not (Map#{2 => 1, 3 => 17} |> toDelayMap |> + DelayMap.memberOf(5))) + + @Test + def memberOf05(): Unit \ Assert = + assertTrue(Map#{2 => 1, 5 => 17} |> toDelayMap |> + DelayMap.memberOf(5)) + + @Test + def memberOf06(): Unit \ Assert = + assertTrue(Map#{5 => 1, 3 => 17} |> toDelayMap |> + DelayMap.memberOf(5)) + + @Test + def memberOf07(): Unit \ Assert = + assertTrue(not (Map#{2 => 1, 3 => 17, -1 => -2} |> toDelayMap |> + DelayMap.memberOf(-2))) + + @Test + def memberOf08(): Unit \ Assert = + assertTrue(Map#{-2 => 1, 3 => 17, -1 => -2} |> toDelayMap |> + DelayMap.memberOf(-2)) + + @Test + def memberOf09(): Unit \ Assert = + assertTrue(Map#{2 => 1, -2 => 17, -1 => -2} |> toDelayMap |> + DelayMap.memberOf(-2)) + + @Test + def memberOf10(): Unit \ Assert = + assertTrue(Map#{2 => 1, 3 => 17, -2 => -2} |> toDelayMap |> + DelayMap.memberOf(-2)) + + + ///////////////////////////////////////////////////////////////////////////// + // keysOf // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def keysOf01(): Unit \ Assert = + assertEq(expected = Set#{}, (Map#{}: Map[Unit, Unit]) |> toDelayMap |> + DelayMap.keysOf) + + @Test + def keysOf02(): Unit \ Assert = + assertEq(expected = Set#{1}, Map#{1 => 2} |> toDelayMap |> + DelayMap.keysOf) + + @Test + def keysOf03(): Unit \ Assert = + assertEq(expected = Set#{1, 2}, Map#{1 => 2, 2 => 4} |> toDelayMap |> + DelayMap.keysOf) + + @Test + def keysOf04(): Unit \ Assert = + assertEq(expected = Set#{1, 2, 3}, Map#{1 => 2, 2 => 4, 3 => 6} |> toDelayMap |> + DelayMap.keysOf) + + @Test + def keysOf05(): Unit \ Assert = + assertEq(expected = Set#{1, 2, 3, 4}, Map#{1 => 2, 2 => 4, 3 => 6, 4 => 8} |> toDelayMap |> + DelayMap.keysOf) + + @Test + def keysOf06(): Unit \ Assert = + assertEq(expected = Set#{1, 2, 3, 4, 5}, Map#{1 => 2, 2 => 4, 3 => 6, 4 => 8, 5 => 10} |> toDelayMap |> + DelayMap.keysOf) + + + ///////////////////////////////////////////////////////////////////////////// + // valuesOf // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def valuesOf01(): Unit \ Assert = + assertEq(expected = Nil, (Map#{}: Map[Unit, Unit]) |> toDelayMap |> + DelayMap.valuesOf) + + @Test + def valuesOf02(): Unit \ Assert = + assertEq(expected = 2 :: Nil, Map#{1 => 2} |> toDelayMap |> + DelayMap.valuesOf) + + @Test + def valuesOf03(): Unit \ Assert = + assertEq(expected = 2 :: 4 :: Nil, Map#{1 => 2, 2 => 4} |> toDelayMap |> + DelayMap.valuesOf) + + @Test + def valuesOf04(): Unit \ Assert = + assertEq(expected = 2 :: 4 :: 6 :: Nil, Map#{1 => 2, 2 => 4, 3 => 6} |> toDelayMap |> + DelayMap.valuesOf) + + @Test + def valuesOf05(): Unit \ Assert = + assertEq(expected = 2 :: 4 :: 6 :: 8 :: Nil, Map#{1 => 2, 2 => 4, 3 => 6, 4 => 8} |> toDelayMap |> + DelayMap.valuesOf) + + @Test + def valuesOf06(): Unit \ Assert = + assertEq(expected = 2 :: 4 :: 6 :: 8 :: 10 :: Nil, Map#{1 => 2, 2 => 4, 3 => 6, 4 => 8, 5 => 10} |> toDelayMap |> + DelayMap.valuesOf) + + @Test + def valuesOf07(): Unit \ Assert = + assertEq(expected = -11 :: 4 :: -5 :: 7 :: -5 :: Nil, Map#{1 => -11, 2 => 4, 3 => -5, 4 => 7, 5 => -5} |> toDelayMap |> + DelayMap.valuesOf) + + + ///////////////////////////////////////////////////////////////////////////// + // minimumKey // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def minimumKey01(): Unit \ Assert = + assertEq(expected = None, (Map#{}: Map[Unit, Int32]) |> toDelayMap |> + DelayMap.minimumKey) + + @Test + def minimumKey02(): Unit \ Assert = + assertEq(expected = Some((1, 2)), Map#{1 => 2, 2 => 3, 3 => 4, 5 => 5} |> toDelayMap |> + DelayMap.minimumKey) + + @Test + def minimumKey03(): Unit \ Assert = + assertEq(expected = Some((0, 2)), Map#{1 => 2, 2 => 3, 3 => 4, 5 => 5, 0 => 2} |> toDelayMap |> + DelayMap.minimumKey) + + @Test + def minimumKey04(): Unit \ Assert = + assertEq(expected = Some((-44, 4)), Map#{1 => 2, 2 => 3, -44 => 4, 5 => 5, 0 => 2} |> toDelayMap |> + DelayMap.minimumKey) + + + ///////////////////////////////////////////////////////////////////////////// + // minimumKeyBy // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def minimumKeyBy01(): Unit \ Assert = + assertEq(expected = None, (Map#{}: Map[Unit, Int32]) |> toDelayMap |> + DelayMap.minimumKeyBy((x, y) -> x <=> y)) + + @Test + def minimumKeyBy02(): Unit \ Assert = + assertEq(expected = Some((1, 2)), Map#{1 => 2, 2 => 3, 3 => 4, 5 => 5} |> toDelayMap |> + DelayMap.minimumKeyBy((x, y) -> x <=> y)) + + @Test + def minimumKeyBy03(): Unit \ Assert = + assertEq(expected = Some((0, 2)), Map#{1 => 2, 2 => 3, 3 => 4, 5 => 5, 0 => 2} |> toDelayMap |> + DelayMap.minimumKeyBy((x, y) -> x <=> y)) + + @Test + def minimumKeyBy04(): Unit \ Assert = + assertEq(expected = Some((-44, 4)), Map#{1 => 2, 2 => 3, -44 => 4, 5 => 5, 0 => 2} |> toDelayMap |> + DelayMap.minimumKeyBy((x, y) -> x <=> y)) + + + ///////////////////////////////////////////////////////////////////////////// + // maximumKey // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def maximumKey01(): Unit \ Assert = + assertEq(expected = None, (Map#{}: Map[Unit, Int32]) |> toDelayMap |> + DelayMap.maximumKey) + + @Test + def maximumKey02(): Unit \ Assert = + assertEq(expected = Some((5, 5)), Map#{1 => 2, 2 => 3, 3 => 4, 5 => 5} |> toDelayMap |> + DelayMap.maximumKey) + + @Test + def maximumKey03(): Unit \ Assert = + assertEq(expected = Some((5, 5)), Map#{1 => 2, 2 => 3, 3 => 4, 5 => 5, 0 => 2} |> toDelayMap |> + DelayMap.maximumKey) + + @Test + def maximumKey04(): Unit \ Assert = + assertEq(expected = Some((107, -107)), Map#{1 => 2, 2 => 3, 107 => -107, 5 => 5, 0 => 2} |> toDelayMap |> + DelayMap.maximumKey) + + + ///////////////////////////////////////////////////////////////////////////// + // maximumKeyBy // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def maximumKeyBy01(): Unit \ Assert = + assertEq(expected = None, (Map#{}: Map[Unit, Int32]) |> toDelayMap |> + DelayMap.maximumKeyBy((x, y) -> x <=> y)) + + @Test + def maximumKeyBy02(): Unit \ Assert = + assertEq(expected = Some((5, 5)), Map#{1 => 2, 2 => 3, 3 => 4, 5 => 5} |> toDelayMap |> + DelayMap.maximumKeyBy((x, y) -> x <=> y)) + + @Test + def maximumKeyBy03(): Unit \ Assert = + assertEq(expected = Some((5, 5)), Map#{1 => 2, 2 => 3, 3 => 4, 5 => 5, 0 => 2} |> toDelayMap |> + DelayMap.maximumKeyBy((x, y) -> x <=> y)) + + @Test + def maximumKeyBy04(): Unit \ Assert = + assertEq(expected = Some((107, -107)), Map#{1 => 2, 2 => 3, 107 => -107, 5 => 5, 0 => 2} |> toDelayMap |> + DelayMap.maximumKeyBy((x, y) -> x <=> y)) + + + ///////////////////////////////////////////////////////////////////////////// + // iterator // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def iterator01(): Unit \ Assert = region rc { + assertEq(expected = Map.empty(), (Map.empty(): Map[Int32, Int32]) |> toDelayMap |> + DelayMap.iterator(rc) |> Iterator.toMap) + } + + @Test + def iterator02(): Unit \ Assert = region rc { + assertEq(expected = Map#{"A" => 1, "B" => 2, "C" => 3, "D" => 4}, Map#{"A" => 1, "B" => 2, "C" => 3, "D" => 4} |> toDelayMap |> + DelayMap.iterator(rc) |> Iterator.toMap) + } + + @Test + def iterator03(): Unit \ Assert = region rc { + let l = List.range(0, 100); + assertEq(expected = List.zip(List.range(0, 100), List.reverse(List.range(0, 100))), List.zip(l, List.reverse(l)) |> List.toMap |> toDelayMap |> + DelayMap.iterator(rc) |> Iterator.toMap |> Map.toList) + } + + ///////////////////////////////////////////////////////////////////////////// + // sumValues // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def sumValues01(): Unit \ Assert = + assertEq(expected = 0, DelayMap.empty() |> DelayMap.sumValues) + + @Test + def sumValues02(): Unit \ Assert = + assertEq(expected = 1, Map#{1 => 1} |> toDelayMap |> + DelayMap.sumValues) + + @Test + def sumValues03(): Unit \ Assert = + assertEq(expected = 6, Map#{1 => 1, 2 => 2, 3 => 3} |> toDelayMap |> + DelayMap.sumValues) + + @Test + def sumValues04(): Unit \ Assert = + assertEq(expected = 3, Map#{1 => 1, 2 => 2, 3 => 3, -3 => -3} |> toDelayMap |> + DelayMap.sumValues) + + @Test + def sumValues05(): Unit \ Assert = + assertEq(expected = -10, Map#{-1 => -1, -2 => -2, -3 => -3, -4 => -4} |> toDelayMap |> + DelayMap.sumValues) + + @Test + def sumValues06(): Unit \ Assert = + assertEq(expected = 0, Map#{10 => 10, -10 => -10} |> toDelayMap |> + DelayMap.sumValues) + + @Test + def sumValues07(): Unit \ Assert = + assertEq(expected = 5050, List.range(1, 101) |> List.zip(List.range(1, 101)) |> List.toMap |> toDelayMap |> + DelayMap.sumValues) + + + ///////////////////////////////////////////////////////////////////////////// + // sumKeys // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def sumKeys01(): Unit \ Assert = + assertEq(expected = 0, DelayMap.empty() |> DelayMap.sumKeys) + + @Test + def sumKeys02(): Unit \ Assert = + assertEq(expected = 1, Map#{1 => 1} |> toDelayMap |> + DelayMap.sumKeys) + + @Test + def sumKeys03(): Unit \ Assert = + assertEq(expected = 6, Map#{1 => 1, 2 => 2, 3 => 3} |> toDelayMap |> + DelayMap.sumKeys) + + @Test + def sumKeys04(): Unit \ Assert = + assertEq(expected = 3, Map#{1 => 1, 2 => 2, 3 => 3, -3 => -3} |> toDelayMap |> + DelayMap.sumKeys) + + @Test + def sumKeys05(): Unit \ Assert = + assertEq(expected = -12, Map#{-1 => -1, -2 => -2, -5 => -3, -4 => -4} |> toDelayMap |> + DelayMap.sumKeys) + + @Test + def sumKeys06(): Unit \ Assert = + assertEq(expected = 0, Map#{10 => 10, -10 => -10} |> toDelayMap |> + DelayMap.sumKeys) + + @Test + def sumKeys07(): Unit \ Assert = + assertEq(expected = 5050, List.range(1, 101) |> List.zip(List.range(1, 101)) |> List.toMap |> toDelayMap |> + DelayMap.sumKeys) + + + ///////////////////////////////////////////////////////////////////////////// + // sumWith // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def sumWith01(): Unit \ Assert = + assertEq(expected = 0, DelayMap.empty() |> DelayMap.sumWith((k, v) -> k + v)) + + @Test + def sumWith02(): Unit \ Assert = + assertEq(expected = 2, Map#{1 => 1} |> toDelayMap |> + DelayMap.sumWith((k, v) -> k + v)) + + @Test + def sumWith03(): Unit \ Assert = + assertEq(expected = 12, Map#{1 => 1, 2 => 2, 3 => 3} |> toDelayMap |> + DelayMap.sumWith((k, v) -> k + v)) + + @Test + def sumWith04(): Unit \ Assert = + assertEq(expected = 6, Map#{1 => 1, 2 => 2, 3 => 3, -3 => -3} |> toDelayMap |> + DelayMap.sumWith((k, v) -> k + v)) + + @Test + def sumWith05(): Unit \ Assert = + assertEq(expected = -20, Map#{-1 => -1, -2 => -2, -3 => -3, -4 => -4} |> toDelayMap |> + DelayMap.sumWith((k, v) -> k + v)) + + @Test + def sumWith06(): Unit \ Assert = + assertEq(expected = 0, Map#{10 => 10, -10 => -10} |> toDelayMap |> + DelayMap.sumWith((k, v) -> k + v)) + + @Test + def sumWith07(): Unit \ Assert = region rc { + let range = List.range(0, 2000); + let m = List.zip(range, range) |> List.toMap |> toDelayMap; + let a = MutList.empty(rc); + discard DelayMap.sumWith((k, _) -> { let b = MutList.empty(rc); MutList.push(k, b); MutList.append(MutList.toList(b), a); 0 }, m); + assertEq(expected = range, MutList.toList(a)) + } + + + ///////////////////////////////////////////////////////////////////////////// + // joinKeys // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def joinKeys01(): Unit \ Assert = + assertEq(expected = "", (DelayMap.empty(): DelayMap[Int32, Int32]) |> DelayMap.joinKeys(",")) + + @Test + def joinKeys02(): Unit \ Assert = + assertEq(expected = "1", Map#{1 => 1} |> toDelayMap |> DelayMap.joinKeys(",")) + + @Test + def joinKeys03(): Unit \ Assert = + assertEq(expected = "0,1,2", Map#{0 => 1, 1 => 2, 2 => 2} |> toDelayMap |> DelayMap.joinKeys(",")) + + @Test + def joinKeys04(): Unit \ Assert = + assertEq(expected = "0,1,2", Map#{"0" => 1, "1" => 2, "2" => 2} |> toDelayMap |> DelayMap.joinKeys(",")) + + + ///////////////////////////////////////////////////////////////////////////// + // joinValues // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def joinValues01(): Unit \ Assert = + assertEq(expected = "", (DelayMap.empty(): DelayMap[Int32, Int32]) |> DelayMap.joinValues(",")) + + @Test + def joinValues02(): Unit \ Assert = + assertEq(expected = "1", Map#{1 => 1} |> toDelayMap |> DelayMap.joinValues(",")) + + @Test + def joinValues03(): Unit \ Assert = + assertEq(expected = "1,2,2", Map#{0 => 1, 1 => 2, 2 => 2} |> toDelayMap |> DelayMap.joinValues(",")) + + @Test + def joinValues04(): Unit \ Assert = + assertEq(expected = "1,2,2", Map#{0 => "1", 1 => "2", 2 => "2"} |> toDelayMap |> DelayMap.joinValues(",")) + + + ///////////////////////////////////////////////////////////////////////////// + // joinWith // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def joinWith01(): Unit \ Assert = + assertEq(expected = "", (Map.empty(): Map[Int32, Int32]) |> toDelayMap |> + DelayMap.joinWith((k, v) -> "${k} => ${v}", ",")) + + @Test + def joinWith02(): Unit \ Assert = + assertEq(expected = "1 => 1", Map#{1 => 1} |> toDelayMap |> + DelayMap.joinWith((k, v) -> "${k} => ${v}", ", ")) + + @Test + def joinWith03(): Unit \ Assert = + assertEq(expected = "0 => 1, 1 => 2, 2 => 2", Map#{0 => 1, 1 => 2, 2 => 2} |> toDelayMap |> + DelayMap.joinWith((k, v) -> "${k} => ${v}", ", ")) + + @Test + def joinWith04(): Unit \ Assert = + assertEq(expected = "0 => 1, 1 => 2, 2 => 2", Map#{0 => "1", 1 => "2", 2 => "2"} |> toDelayMap |> + DelayMap.joinWith((k, v) -> "${k} => ${v}", ", ")) + + + ///////////////////////////////////////////////////////////////////////////// + // toString // + ///////////////////////////////////////////////////////////////////////////// + + @Test + def toString01(): Unit \ Assert = + assertEq(expected = "DelayMap#{1 => 2}", ToString.toString(Map#{1 => 2} |> toDelayMap)) + + @Test + def toString02(): Unit \ Assert = + assertEq(expected = "DelayMap#{1 => 0, 2 => 1, 3 => 2}", ToString.toString(Map#{1 => 0, 2 => 1, 3 => 2} |> toDelayMap)) + + @Test + def toString03(): Unit \ Assert = + assertEq(expected = "DelayMap#{1 => b, 2 => a}", ToString.toString(Map#{1 => "b", 2 => "a"} |> toDelayMap)) + + @Test + def toString04(): Unit \ Assert = + assertEq(expected = "DelayMap#{0 => true, 2 => true, 3 => false, 4 => true, 97 => false}", ToString.toString(Map#{97 => false, 2 => true, 3 => false, 4 => true, 0 => true} |> toDelayMap)) + + @Test + def toString05(): Unit \ Assert = + assertEq(expected = "DelayMap#{2 => Map#{1 => 0, 2 => 1}, 3 => Map#{3 => 2, 4 => 92}}", ToString.toString(Map#{2 => Map#{1 => 0, 2 => 1}, 3 => Map#{3 => 2, 4 => 92}} |> toDelayMap)) + + +}