/* * Copyright 2021 Jakob Schneider Villumsen * * Use of this source code is governed by the Apache 2.0 license * that can be found in the LICENSE.md file. */pubmod DelayList {use Math.ShufflepubenumDelayList[a] {case ENilcase ECons(a, DelayList[a])case LCons(a, Lazy[DelayList[a]])case LList(Lazy[DelayList[a]]) }instanceEq[DelayList[a]] withEq[a] {pubdefeq(l1: DelayList[a], l2: DelayList[a]): Bool = match (l1, l2) {case (DelayList.ENil, DelayList.ENil) => truecase (DelayList.ECons(x, xs), DelayList.ECons(y, ys)) => if (x!=y) falseelsexs==yscase (DelayList.ECons(x, xs), DelayList.LCons(y, ys)) => if (x!=y) falseelsexs==forceyscase (DelayList.LCons(x, xs), DelayList.ECons(y, ys)) => if (x!=y) falseelse (forcexs) ==yscase (DelayList.LCons(x, xs), DelayList.LCons(y, ys)) => if (x!=y) falseelse (forcexs) ==forceyscase (DelayList.LList(xs), DelayList.LList(ys)) => (forcexs) ==forceyscase (l, DelayList.LList(ys)) => l==forceyscase (DelayList.LList(xs), l) => (forcexs) ==lcase_ => false } }instanceOrder[DelayList[a]] withOrder[a] {////// Compares `l1` and `l2` lexicographically.///pubdefcompare(l1: DelayList[a], l2: DelayList[a]): Comparison = match (l1, l2) {case (DelayList.ENil, DelayList.ENil) => Comparison.EqualTocase (_, DelayList.ENil) => Comparison.GreaterThancase (DelayList.ENil, _) => Comparison.LessThancase (DelayList.LList(xs), DelayList.LList(ys)) => (forcexs) <=> (forceys)case (_, DelayList.LList(ys)) => l1<=> (forceys)case (DelayList.LList(xs), _) => (forcexs) <=>l2case (DelayList.ECons(x, xs), DelayList.ECons(y, ys)) =>letcmp = x<=>y;if (cmp== Comparison.EqualTo) xs<=>yselsecmpcase (DelayList.ECons(x, xs), DelayList.LCons(y, ys)) =>letcmp = x<=>y;if (cmp== Comparison.EqualTo) xs<=> (forceys) elsecmpcase (DelayList.LCons(x, xs), DelayList.ECons(y, ys)) =>letcmp = x<=>y;if (cmp== Comparison.EqualTo) (forcexs) <=>yselsecmpcase (DelayList.LCons(x, xs), DelayList.LCons(y, ys)) =>letcmp = x<=>y;if (cmp== Comparison.EqualTo) (forcexs) <=> (forceys) elsecmp } }instanceToString[DelayList[a]] withToString[a] {pubdeftoString(l: DelayList[a]): String = DelayList.toString(l) }instanceFoldable[DelayList] {pubdeffoldLeft(f: (b, a) -> b \ ef, s: b, l: DelayList[a]): b \ ef = DelayList.foldLeft(f, s, l)pubdeffoldRight(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]): BoolwithEq[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) }instanceUnorderedFoldable[DelayList] {pubdeffoldMap(f: a -> b \ ef, l: DelayList[a]): b \ efwithCommutativeMonoid[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]): BoolwithEq[a] = DelayList.memberOf(x, l) }instanceFunctor[DelayList] {pubdefmap(f: a -> b \ ef, l: DelayList[a]): DelayList[b] \ ef = DelayList.map(f, l) }instanceApplicative[DelayList] {pubdefpoint(x: a): DelayList[a] = DelayList.singleton(x)pubdefap(f: DelayList[a -> b \ ef], l: DelayList[a]): DelayList[b] \ ef = DelayList.ap(f, l) }instanceMonad[DelayList] {pubdefflatMap(f: a -> DelayList[b] \ ef, l: DelayList[a]): DelayList[b] \ ef = DelayList.flatMap(f, l) }instanceMonadZero[DelayList] {pubdefempty(): DelayList[a] = DelayList.empty() }instanceTraversable[DelayList] {pubdeftraverse(f: a -> m[b] \ ef, l: DelayList[a]): m[DelayList[b]] \ efwithApplicative[m] = DelayList.traverse(f, l) redef sequence(l: DelayList[m[a]]): m[DelayList[a]] withApplicative[m] = DelayList.sequence(l) }instanceFilterable[DelayList] {pubdeffilterMap(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) }instanceWitherable[DelayList]instanceSemiGroup[DelayList[a]] {pubdefcombine(l1: DelayList[a], l2: DelayList[a]): DelayList[a] = DelayList.append(l1, l2) }instanceMonoid[DelayList[a]] {pubdefempty(): DelayList[a] = DelayList.ENil }instanceIterable[DelayList[a]] {typeElm = apubdefiterator(rc: Region[r], l: DelayList[a]): Iterator[a, r, r] \ r = DelayList.iterator(rc, l) }instanceForEach[DelayList[a]] {typeElm = apubdefforEach(f: a -> Unit \ ef, l: DelayList[a]): Unit \ ef = DelayList.forEach(f, l) }////// Returns a string representation of `l`.////// Forces the entire list `l`.///@ExperimentalpubdeftoString(l: DelayList[a]): StringwithToString[a] = regionrc {"DelayList("+ (DelayList.iterator(rc, l) |> Iterator.join(", ")) +")" }////// Returns an empty DelayList.///@Experimentalpubdefempty(): DelayList[a] = ENil////// Returns true if and only if `l` is the empty DelayList, i.e. `ENil`.////// Does not force the tail of `l`.///@ExperimentalpubdefisEmpty(l: DelayList[a]): Bool = matchl {case ENil => truecase LList(xs) => isEmpty(forcexs)case_ => false }////// Returns true if and only if `l` is a non-empty DelayList.////// Does not force the tail of `l`.///@ExperimentalpubdefnonEmpty(l: DelayList[a]): Bool = notisEmpty(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`.///@Experimentalpubdefhead(l: DelayList[a]): Option[a] = matchl {case ENil => Nonecase ECons(x, _) => Some(x)case LCons(x, _) => Some(x)case LList(xs) => head(forcexs) }////// Returns `Some(x)` if `x` is the last element of `l`.////// Returns `None` if `l` is empty.////// Forces the entire list `l`.///@Experimentalpubdeflast(l: DelayList[a]): Option[a] = matchl {case ENil => Nonecase ECons(x, xs) => if (isEmpty(xs)) Some(x) elselast(xs)case LCons(x, xs) => if (isEmpty(forcexs)) Some(x) elselast(forcexs)case LList(xs) => last(forcexs) }////// 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.///@Experimentalpubdeftail(l: DelayList[a]): Option[DelayList[a]] = matchl {case ENil => Nonecase ECons(_, xs) => Some(xs)case LCons(_, xs) => Some(LList(xs))case LList(xs) => tail(forcexs) }////// Returns `Some(xs)` where `xs` is `l` without the last element.////// Returns `None` if `l` is empty.////// Forces the entire list `l`.///@Experimentalpubdefinit(l: DelayList[a]): Option[DelayList[a]] =defloop(prev, ll, acc) = matchll {case ENil => acccase ECons(x, xs) => loop(x, xs, ECons(prev, acc))case LCons(x, xs) => loop(x, forcexs, ECons(prev, acc))case LList(xs) => loop(prev, forcexs, acc) };matchl {case ENil => Nonecase ECons(x, xs) => Some(reverse(loop(x, xs, ENil)))case LCons(x, xs) => Some(reverse(loop(x, forcexs, ENil)))case LList(xs) => init(forcexs) }////// Returns the number of elements in `l`.////// Forces the entire list `l`.///@Experimentalpubdeflength(l: DelayList[a]): Int32 =defloop(ll, acc) = matchll {case ENil => acccase ECons(_, xs) => loop(xs, acc+1)case LCons(_, xs) => loop(forcexs, acc+1)case LList(xs) => loop(forcexs, acc) };loop(l, 0)////// Returns the number of elements in `l`.////// Forces the entire list `l`.///@Experimentalpubdefsize(l: DelayList[a]): Int32 = length(l)////// Returns `l2` appended to `l1`.////// Does not force the tail of `l1`.///@Experimental@Lazypubdefappend(l1: DelayList[a], l2: DelayList[a]): DelayList[a] = matchl1 {case ENil => l2case ECons(x, xs) => LCons(x, lazyappend(xs, l2))case LCons(x, xs) => LCons(x, lazyappend(forcexs, l2))case LList(xs) => LList(lazyappend(forcexs, l2)) }////// Returns the number of elements in `l` that satisfy the predicate `f`.////// Forces the entire list `l`.///@Experimentalpubdefcount(f: a -> Bool \ ef, l: DelayList[a]): Int32 \ ef =foldLeft((i, x) -> if (f(x)) i+1elsei, 0, l)////// Returns the sum of all elements in the DelayList `l`.////// Forces the entire list `l`.///@Experimentalpubdefsum(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`.///@ExperimentalpubdefsumWith(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@Lazypubdefflatten(l: DelayList[DelayList[a]]): DelayList[a] = matchl {case ENil => ENilcase ECons(x, xs) => append(x, LList(lazyflatten(xs)))case LCons(x, xs) => append(x, LList(lazyflatten(forcexs)))case LList(xs) => LList(lazyflatten(forcexs)) }////// 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.///@Experimentalpubdefexists(f: a -> Bool \ ef, l: DelayList[a]): Bool \ ef = matchl {case ENil => falsecase ECons(x, xs) => if (f(x)) trueelseexists(f, xs)case LCons(x, xs) => if (f(x)) trueelseexists(f, forcexs)case LList(xs) => exists(f, forcexs) }////// 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).///@ExperimentalpubdefforAll(f: a -> Bool \ ef, l: DelayList[a]): Bool \ ef = matchl {case ENil => truecase ECons(x, xs) => if (f(x)) forAll(f, xs) elsefalsecase LCons(x, xs) => if (f(x)) forAll(f, forcexs) elsefalsecase LList(xs) => forAll(f, forcexs) }////// Returns `true` if and only if `l` contains the element `x`.////// Forces elements until `x` is found.///@ExperimentalpubdefmemberOf(x: a, l: DelayList[a]): BoolwithEq[a] = matchl {case ENil => falsecase ECons(x1, xs) => if (x1==x) trueelsememberOf(x, xs)case LCons(x1, xs) => if (x1==x) trueelsememberOf(x, forcexs)case LList(xs) => memberOf(x, forcexs) }////// Optionally finds the smallest element of `l` according to the `Order` on `a`.////// Returns `None` if `l` is empty.////// Forces the entire list `l`.///@Experimentalpubdefminimum(l: DelayList[a]): Option[a] withOrder[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`.///@ExperimentalpubdefminimumBy(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`.///@Experimentalpubdefmaximum(l: DelayList[a]): Option[a] withOrder[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`.///@ExperimentalpubdefmaximumBy(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@Lazypubdefrange(b: Int32, e: Int32): DelayList[Int32] =defloop(i) = {if (i>=e) ENilelse LCons(i, lazyloop(i+1)) }; LList(lazyloop(b))////// Returns an infinite DelayList of repeating `x`s.///@Experimental@Lazypubdefrepeat(x: a): DelayList[a] = LCons(x, lazyrepeat(x))////// Returns an infinite sequence of integers starting from and including `n`.///@Experimental@LazypubdefstartFrom(n: Int32): DelayList[Int32] =defloop(i) = LCons(i, lazyloop(i+1)); LList(lazyloop(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@LazyWhenPurepubdefmap(f: a -> b \ ef, l: DelayList[a]): DelayList[b] \ ef =matchpurityOf(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).///@LazydefmapL(f: a -> b, l: DelayList[a]): DelayList[b] = matchl {case ENil => ENilcase ECons(x, xs) => LCons(f(x), lazymapL(f, xs))case LCons(x, xs) => LCons(f(x), lazymapL(f, forcexs))case LList(xs) => LList(lazymapL(f, forcexs)) }////// Returns the result of applying `f` to every element in `l`.////// Applies `f` eagerly (i.e. the entire list `l` is forced).///defmapE(f: a -> b \ ef, l: DelayList[a]): DelayList[b] \ ef =defloop(ll, k) = matchll {case ENil => k(ENil)case ECons(x, xs) =>letx1 = f(x);loop(xs, ks -> k(ECons(x1, ks)))case LCons(x, xs) =>letx1 = f(x);loop(forcexs, ks -> k(ECons(x1, ks)))case LList(xs) =>loop(forcexs, 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@LazyWhenPurepubdefmapWithIndex(f: (Int32, a) -> b \ ef, l: DelayList[a]): DelayList[b] \ ef =matchpurityOf2(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).///@LazydefmapWithIndexL(f: (Int32, a) -> b, l: DelayList[a]): DelayList[b] =defloop(ll, i) = matchll {case ENil => ENilcase ECons(x, xs) => LCons(f(i, x), lazyloop(xs, i+1))case LCons(x, xs) => LCons(f(i, x), lazyloop(forcexs, i+1))case LList(xs) => LList(lazyloop(forcexs, i)) }; LList(lazyloop(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).///defmapWithIndexE(f: (Int32, a) -> b \ ef, l: DelayList[a]): DelayList[b] \ ef =defloop(ll, i, k) = matchll {case ENil => k(ENil)case ECons(x, xs) =>letx1 = f(i, x);loop(xs, i+1, ks -> k(ECons(x1, ks)))case LCons(x, xs) =>letx1 = f(i, x);loop(forcexs, i+1, ks -> k(ECons(x1, ks)))case LList(xs) => loop(forcexs, 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@LazyWhenPurepubdefflatMap(f: a -> DelayList[b] \ ef, l: DelayList[a]): DelayList[b] \ ef =matchpurityOf(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).///@LazydefflatMapL(f: a -> DelayList[b], l: DelayList[a]): DelayList[b] = matchl {case ENil => ENilcase ECons(x, xs) => append(f(x), LList(lazyflatMapL(f, xs)))case LCons(x, xs) => append(f(x), LList(lazyflatMapL(f, forcexs)))case LList(xs) => LList(lazyflatMapL(f, forcexs)) }////// 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).///defflatMapE(f: a -> DelayList[b] \ ef, l: DelayList[a]): DelayList[b] \ ef =defloop(ll, k) = matchll {case ENil => k(ENil)case ECons(x, xs) =>letxs1 = f(x);loop(xs, ks -> k(append(xs1, ks)))case LCons(x, xs) =>letxs1 = f(x);loop(forcexs, ks -> k(append(xs1, ks)))case LList(xs) => loop(forcexs, k) };loop(l, identity)////// Return the singleton list with element `x`.///@Experimentalpubdefsingleton(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@LazyWhenPurepubdefap(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@Lazypubdefreverse(l: DelayList[a]): DelayList[a] =defloop(ll, acc) = matchll {case ENil => acccase ECons(x, xs) => loop(xs, ECons(x, acc))case LCons(x, xs) => loop(forcexs, ECons(x, acc))case LList(xs) => loop(forcexs, acc) }; LList(lazyloop(l, ENil))////// Returns `l` with every occurrence of `src` replaced by `dst`.////// Does not force the tail of `l`.///@Experimental@Lazypubdefreplace(src: {src = a}, dst: {dst = a}, l: DelayList[a]): DelayList[a] withEq[a] =map(e -> if (src#src ==e) dst#dst elsee, 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`.///@ExperimentalpubdeffoldLeft(f: (b, a) -> b \ ef, s: b, l: DelayList[a]): b \ ef = matchl {case ENil => scase ECons(x, xs) => foldLeft(f, f(s, x), xs)case LCons(x, xs) => foldLeft(f, f(s, x), forcexs)case LList(xs) => foldLeft(f, s, forcexs) }////// 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`.///@ExperimentalpubdeffoldRight(f: (a, b) -> b \ ef, s: b, l: DelayList[a]): b \ ef =defloop(ll, k) = matchll {case ENil => k(s)case ECons(x, xs) => loop(xs, ks -> k(f(x, ks)))case LCons(x, xs) => loop(forcexs, ks -> k(f(x, ks)))case LList(xs) => loop(forcexs, k) };loop(l, x -> checked_ecast(x))////// Returns the result of mapping each element and combining the results.///pubdeffoldMap(f: a -> b \ ef, l: DelayList[a]): b \ efwithMonoid[b] =foldLeft((acc, x) -> Monoid.combine(acc, f(x)), Monoid.empty(), l)////// Applies `f` to every element of `l`.////// Forces the entire list `l`.///@ExperimentalpubdefforEach(f: a -> Unit \ ef, l: DelayList[a]): Unit \ ef = matchl {case ENil => ()case ECons(x, xs) => f(x); forEach(f, xs)case LCons(x, xs) => f(x); forEach(f, forcexs)case LList(xs) => forEach(f, forcexs) }////// Applies `f` to every element of `l` along with that element's index.////// Forces the entire list `l`.///@ExperimentalpubdefforEachWithIndex(f: (Int32, a) -> Unit \ ef, l: DelayList[a]): Unit \ ef = regionrc {letix = Ref.fresh(rc, 0);letf1 = x -> { leti = 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`.///@ExperimentalpubdefreduceLeft(f: (a, a) -> a \ ef, l: DelayList[a]): Option[a] \ ef = matchl {case ENil => Nonecase ECons(x, xs) => Some(foldLeft(f, x, xs))case LCons(x, xs) => Some(foldLeft(f, x, forcexs))case LList(xs) => reduceLeft(f, forcexs) }////// 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`.///@ExperimentalpubdefreduceRight(f: (a, a) -> a \ ef, l: DelayList[a]): Option[a] \ ef =defloop(ll, k) = matchll {case ECons(x, xs) => if (isEmpty(xs)) k(x) elseloop(xs, ks -> k(f(x, ks)))case LCons(x, xs) => if (isEmpty(forcexs)) k(x) elseloop(forcexs, ks -> k(f(x, ks)))case LList(xs) => loop(forcexs, 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@LazyWhenPurepubdeffilter(f: a -> Bool \ ef, l: DelayList[a]): DelayList[a] \ ef =matchpurityOf(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).///@LazydeffilterL(f: a -> Bool, l: DelayList[a]): DelayList[a] = matchl {case ENil => ENilcase ECons(x, xs) => if (f(x)) LCons(x, lazyfilterL(f, xs)) else LList(lazyfilterL(f, xs))case LCons(x, xs) => if (f(x)) LCons(x, lazyfilterL(f, forcexs)) else LList(lazyfilterL(f, forcexs))case LList(xs) => LList(lazyfilterL(f, forcexs)) }////// Returns a `DelayList` with every element in `l` that satisfies the predicate `f`.////// Applies `f` eagerly (i.e. the entire list `l` is forced).///deffilterE(f: a -> Bool \ ef, l: DelayList[a]): DelayList[a] \ ef =defloop(ll, k) = matchll {case ENil => k(ENil)case ECons(x, xs) => if (f(x)) loop(xs, ks -> k(ECons(x, ks))) elseloop(xs, k)case LCons(x, xs) => if (f(x)) loop(forcexs, ks -> k(ECons(x, ks))) elseloop(forcexs, k)case LList(xs) => loop(forcexs, 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@LazyWhenPurepubdeffilterMap(f: a -> Option[b] \ ef, l: DelayList[a]): DelayList[b] \ ef =matchpurityOf(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).///@LazydeffilterMapL(f: a -> Option[b], l: DelayList[a]): DelayList[b] =defloop(ll) = matchll {case ENil => ENilcase ECons(x, xs) =>matchf(x) {case None => loop(xs)case Some(v) => LCons(v, lazyloop(xs)) }case LCons(x, xs) =>// Same as above except `xs` is forced.matchf(x) {case None => loop(forcexs)case Some(v) => LCons(v, lazyloop(forcexs)) }case LList(xs) => LList(lazyloop(forcexs)) }; LList(lazyloop(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).///deffilterMapE(f: a -> Option[b] \ ef, l: DelayList[a]): DelayList[b] \ ef =defloop(ll, k) = matchll {case ENil => k(ENil)case ECons(x, xs) => matchf(x) {case None => loop(xs, k)case Some(v) => loop(xs, ks -> k(ECons(v, ks))) }case LCons(x, xs) => matchf(x) {// Same as above except `xs` is forced.case None => loop(forcexs, k)case Some(v) => loop(forcexs, ks -> k(ECons(v, ks))) }case LList(xs) => loop(forcexs, 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.///@ExperimentalpubdeffindLeft(f: a -> Bool \ ef, l: DelayList[a]): Option[a] \ ef = matchl {case ENil => Nonecase ECons(x, xs) => if (f(x)) Some(x) elsefindLeft(f, xs)case LCons(x, xs) => if (f(x)) Some(x) elsefindLeft(f, forcexs)case LList(xs) => findLeft(f, forcexs) }////// Optionally returns the first element of `l` that satisfies the predicate `f` when searching from right to left.////// Forces the entire list `l`.///@ExperimentalpubdeffindRight(f: a -> Bool \ ef, l: DelayList[a]): Option[a] \ ef =defloop(ll, k) = matchll {case ENil => k()case ECons(x, xs) => loop(xs, () -> if (f(x)) Some(x) elsek())case LCons(x, xs) => loop(forcexs, () -> if (f(x)) Some(x) elsek())case LList(xs) => loop(forcexs, 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)`.///@ExperimentalpubdeffindMap(f: a -> Option[b] \ ef, l: DelayList[a]): Option[b] \ ef = matchl {case ENil => Nonecase ECons(x, xs) => matchf(x) {case None => findMap(f, xs)case Some(v) => Some(v) }case LCons(x, xs) => matchf(x) {// Same as above except `xs` is forced.case None => findMap(f, forcexs)case Some(v) => Some(v) }case LList(xs) => findMap(f, forcexs) }////// Returns `l` with `x` inserted between every two adjacent elements.////// Does not force the tail of `l`.///@Experimental@Lazypubdefintersperse(x: a, l: DelayList[a]): DelayList[a] = matchl {case ENil => ENilcase ECons(x1, xs) => if (isEmpty(xs)) lelse LCons(x1, lazy LCons(x, lazyintersperse(x, xs)))case LCons(x1, xs) => if (isEmpty(forcexs)) lelse LCons(x1, lazy LCons(x, lazyintersperse(x, forcexs)))case LList(xs) => LList(lazyintersperse(x, forcexs)) }////// 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@Lazypubdefintercalate(l1: DelayList[a], l2: DelayList[DelayList[a]]): DelayList[a] = matchl2 {case ENil => ENilcase ECons(x, xs) => if (isEmpty(xs)) xelseappend(append(x, l1), intercalate(l1, xs))case LCons(x, xs) => if (isEmpty(forcexs)) xelseappend(append(x, l1), intercalate(l1, forcexs))case LList(xs) => LList(lazyintercalate(l1, forcexs)) }////// 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`.///@Experimentalpubdefpartition(f: a -> Bool \ ef, l: DelayList[a]): (DelayList[a], DelayList[a]) \ ef =defloop(ll, k) = matchll {case ENil => k((ENil, ENil))case ECons(x, xs) =>if (f(x))loop(xs, match (ks, ls) -> k((ECons(x, ks), ls)))elseloop(xs, match (ks, ls) -> k((ks, ECons(x, ls))))case LCons(x, xs) =>// Same as above except `xs` is forced.if (f(x))loop(forcexs, match (ks, ls) -> k((ECons(x, ks), ls)))elseloop(forcexs, match (ks, ls) -> k((ks, ECons(x, ls))))case LList(xs) => loop(forcexs, 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@LazyWhenPurepubdefspan(f: a -> Bool \ ef, l: DelayList[a]): (DelayList[a], DelayList[a]) \ ef =matchpurityOf(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).///@LazydefspanL(f: a -> Bool, l: DelayList[a]): (DelayList[a], DelayList[a]) = matchl {case ENil => (ENil, ENil)case ECons(x, xs) =>if (f(x))lett = lazyspanL(f, xs); (LCons(x, lazyfst(forcet)), LList(lazysnd(forcet)))else (ENil, l)case LCons(x, xs) =>// Same as above except `xs` is forced.if (f(x))lett = lazyspanL(f, forcexs); (LCons(x, lazyfst(forcet)), LList(lazysnd(forcet)))else (ENil, l)case LList(xs) => spanL(f, forcexs) }////// Helper function for `span`.////// Applies `f` eagerly (i.e. the entire list `l` is forced).///defspanE(f: a -> Bool \ ef, l: DelayList[a]): (DelayList[a], DelayList[a]) \ ef =defloop(ll, k) = matchll {case ENil => k((ENil, ENil))case ECons(x, xs) =>if (f(x))loop(xs, match (ks, ls) -> k((ECons(x, ks), ls)))elsek((ENil, l))case LCons(x, xs) =>// Same as above except `xs` is forced.if (f(x))loop(forcexs, match (ks, ls) -> k((ECons(x, ks), ls)))elsek((ENil, l))case LList(xs) => loop(forcexs, 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@Lazypubdefdrop(n: Int32, l: DelayList[a]): DelayList[a] =defloop(i, ll) = {// Inner function used here to allow for early terminationif (i<1)llelsematchll {case ENil => llcase ECons(_, xs) => loop(i-1, xs)case LCons(_, xs) => loop(i-1, forcexs)case LList(xs) => loop(i, forcexs) } }; LList(lazyloop(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@LazyWhenPurepubdefdropWhile(f: a -> Bool \ ef, l: DelayList[a]): DelayList[a] \ ef =matchpurityOf(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).///@LazydefdropWhileL(f: a -> Bool, l: DelayList[a]): DelayList[a] =defloop(ll) = matchll {// Inner function used here to allow for early terminationcase ENil => ENilcase ECons(x, xs) => if (f(x)) loop(xs) elsellcase LCons(x, xs) => if (f(x)) loop(forcexs) elsellcase LList(xs) => loop(forcexs) }; LList(lazyloop(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`).///defdropWhileE(f: a -> Bool \ ef, l: DelayList[a]): DelayList[a] \ ef = matchl {case ENil => ENilcase ECons(x, xs) => if (f(x)) dropWhileE(f, xs) elselcase LCons(x, xs) => if (f(x)) dropWhileE(f, forcexs) elselcase LList(xs) => dropWhileE(f, forcexs) }////// Returns the first `n` elements of `l`.////// Does not force the tail of `l`.///@Experimental@Lazypubdeftake(n: Int32, l: DelayList[a]): DelayList[a] =defloop(i, ll) = {// Inner function used here to allow for early terminationif (i<=0) ENilelsematchll {case ENil => ENilcase ECons(x, xs) => LCons(x, lazyloop(i-1, xs))case LCons(x, xs) => LCons(x, lazyloop(i-1, forcexs))case LList(xs) => loop(i, forcexs) } }; LList(lazyloop(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@LazyWhenPurepubdeftakeWhile(f: a -> Bool \ ef, l: DelayList[a]): DelayList[a] \ ef =matchpurityOf(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).///@LazydeftakeWhileL(f: a -> Bool, l: DelayList[a]): DelayList[a] =defloop(ll) = matchll {// Inner function used here to allow for early terminationcase ENil => ENilcase ECons(x, xs) => if (f(x)) LCons(x, lazyloop(xs)) else ENilcase LCons(x, xs) => if (f(x)) LCons(x, lazyloop(forcexs)) else ENilcase LList(xs) => loop(forcexs) }; LList(lazyloop(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`).///deftakeWhileE(f: a -> Bool \ ef, l: DelayList[a]): DelayList[a] \ ef =defloop(ll, k) = matchll {case ENil => k(ENil)case ECons(x, xs) => if (f(x)) loop(xs, ks -> k(ECons(x, ks))) elsek(ENil)case LCons(x, xs) => if (f(x)) loop(forcexs, ks -> k(ECons(x, ks))) elsek(ENil)case LList(xs) => loop(forcexs, 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@Lazypubdefzip(l1: DelayList[a], l2: DelayList[b]): DelayList[(a, b)] =defloop(ll1, ll2) = match (ll1, ll2) {// Inner function used here to allow for early terminationcase (ENil, _) => ENilcase (_, ENil) => ENilcase (ECons(x, xs), ECons(y, ys)) => LCons((x, y), lazyloop(xs, ys))case (ECons(x, xs), LCons(y, ys)) => LCons((x, y), lazyloop(xs, forceys))case (LCons(x, xs), ECons(y, ys)) => LCons((x, y), lazyloop(forcexs, ys))case (LCons(x, xs), LCons(y, ys)) => LCons((x, y), lazyloop(forcexs, forceys))case (LList(xs), LList(ys)) => LList(lazyloop(forcexs, forceys))case (xs, LList(ys)) => LList(lazyloop(xs, forceys))case (LList(xs), ys) => LList(lazyloop(forcexs, ys)) };match (l1, l2) {case (ENil, _) => ENilcase (_, ENil) => ENilcase_ => LList(lazyloop(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@LazyWhenPurepubdefzipWith(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`.///pubdefzipWithIndex(l: DelayList[a]): DelayList[(Int32, a)] =defloop(ll, i) = matchll {case ENil => ENilcase ECons(x, xs) => LCons(((i, x)), lazyloop(xs, i+1))case LCons(x, xs) => LCons(((i, x)), lazyloop(forcexs, i+1))case LList(xs) => LList(lazyloop(forcexs, i)) };loop(l, 0)////// Returns `l` as an `Array`.////// Forces the entire list `l`.///@ExperimentalpubdeftoArray(rc: Region[r], l: DelayList[a]): Array[a, r] \ r =leta = 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`.///@ExperimentalpubdeftoVector(l: DelayList[a]): Vector[a] = regionrc {letarr = 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@Lazypubdefiterator(rc: Region[r], l: DelayList[a]): Iterator[a, r, r] \ r =letcursor = Ref.fresh(rc, l);letnext = () -> {letll = Ref.get(cursor);matchhead(ll) {case None => Nonecase 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`.///@ExperimentalpubdeftoList(l: DelayList[a]): List[a] =defloop(ll, k) = matchll {case ENil => k(Nil)case ECons(x, xs) => loop(xs, ks -> k(x :: ks))case LCons(x, xs) => loop(forcexs, ks -> k(x :: ks))case LList(xs) => loop(forcexs, 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`.///@ExperimentalpubdeftoMap(l: DelayList[(a, b)]): Map[a, b] withOrder[a] =defloop(ll, acc) = matchll {case ENil => acccase ECons((k, v), xs) => loop(xs, Map.insert(k, v, acc))case LCons((k, v), xs) => loop(forcexs, Map.insert(k, v, acc))case LList(xs) => loop(forcexs, acc) };loop(l, Map.empty())////// Returns `l` as a `Set`.////// Forces the entire list `l`.///@ExperimentalpubdeftoSet(l: DelayList[a]): Set[a] withOrder[a] =defloop(ll, acc) = matchll {case ENil => acccase ECons(x, xs) => loop(xs, Set.insert(x, acc))case LCons(x, xs) => loop(forcexs, Set.insert(x, acc))case LList(xs) => loop(forcexs, 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`.///@Experimentalpubdefjoin(sep: String, l: DelayList[a]): StringwithToString[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`.///@ExperimentalpubdefjoinWith(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.///@ExperimentaldefconsA(mx: f[a], ml: f[DelayList[a]]): f[DelayList[a]] withApplicative[f] = (((x, xs) -> ECons(x, xs)) `Functor.map`mx) `Applicative.ap`ml////// Returns the result of running all the actions in the DelayList `l`.///@Experimentalpubdefsequence(l: DelayList[m[a]]): m[DelayList[a]] withApplicative[m] =defloop(ll, k) = matchll {case ENil => k(Applicative.point(ENil))case ECons(mx, xs) => loop(xs, ks -> k(consA(mx, ks)))case LCons(mx, xs) => loop(forcexs, ks -> k(consA(mx, ks)))case LList(xs) => loop(forcexs, k) };loop(l, identity)////// Returns the result of applying the applicative mapping function `f` to all the elements of the/// DelayList `l`.///@Experimentalpubdeftraverse(f: a -> m[b] \ ef, l: DelayList[a]): m[DelayList[b]] \ efwithApplicative[m] =defloop(ll, k) = matchll {case ENil => k(Applicative.point(ENil))case ECons(x, xs) => { letans = f(x); loop(xs, ks -> k(consA(ans, ks))) }case LCons(x, xs) => { letans = f(x); loop(forcexs, ks -> k(consA(ans, ks))) }case LList(xs) => loop(forcexs, k) };loop(l, identity)////// Shuffles `l` using the Fisher–Yates shuffle.///pubdefshuffle(l: DelayList[a]): DelayList[a] \ Shuffle = regionrc {deffromList(xs) = matchxs {case Nil => ENilcasey :: ys => ECons(y, fromList(ys)) };toArray(rc, l) !> Array.shuffle |> Array.toList |> fromList }}