/* * Copyright 2021 Stephen Tetley * * Use of this source code is governed by the Apache 2.0 license * that can be found in the LICENSE.md file. */pubmod Chain {use Math.Shuffleuse ViewLeft.{NoneLeft, SomeLeft}use ViewRight.{NoneRight, SomeRight}////// The Chain type.////// A chain is a list represented as an unbalanced binary tree./// It supports efficient append and "snoc" - appending elements at the tail/// of the list.////// Note - the constructors `Empty`, `One` and `Chain` should not be used directly.///pubenumChain[t] {case Emptycase One(t)case Chain(Chain[t], Chain[t]) }instanceEq[Chain[a]] withEq[a] {pubdefeq(c1: Chain[a], c2: Chain[a]): Bool = Chain.equals(c1, c2) }instanceOrder[Chain[a]] withOrder[a] {pubdefcompare(c1: Chain[a], c2: Chain[a]): Comparison = Chain.compare(c1, c2) }instanceSemiGroup[Chain[a]] {pubdefcombine(c1: Chain[a], c2: Chain[a]): Chain[a] = Chain.append(c1, c2) }instanceMonoid[Chain[a]] {pubdefempty(): Chain[a] = Chain.empty() }instanceFunctor[Chain] {pubdefmap(f: a -> b \ ef, c: Chain[a]): Chain[b] \ ef = Chain.map(f, c) }instanceApplicative[Chain] {pubdefpoint(x: a): Chain[a] = Chain.singleton(x)pubdefap(f: Chain[a -> b \ ef], x: Chain[a]): Chain[b] \ ef = Chain.ap(f, x) }instanceMonad[Chain] {pubdefflatMap(f: a -> Chain[b] \ ef, x: Chain[a]): Chain[b] \ ef = Chain.flatMap(f, x) }instanceMonadZero[Chain] {pubdefempty(): Chain[a] = Chain.empty() }instanceMonadZip[Chain] {pubdefzipWith(f: (a, b) -> c \ ef, xs: Chain[a], ys: Chain[b]): Chain[c] \ ef = Chain.zipWith(f, xs, ys)pubdefzipWithA(f: (a, b) -> f[c] \ ef, xs: Chain[a], ys: Chain[b]): f[Chain[c]] \ efwithApplicative[f] = Chain.zipWithA(f, xs, ys) redef zip(xs: Chain[a], ys: Chain[b]): Chain[(a, b)] = Chain.zip(xs, ys) redef unzip(xs: Chain[(a, b)]): (Chain[a], Chain[b]) = Chain.unzip(xs) }instanceFoldable[Chain] {pubdeffoldLeft(f: (b, a) -> b \ ef, s: b, c: Chain[a]): b \ ef = Chain.foldLeft(f, s, c)pubdeffoldRight(f: (a, b) -> b \ ef, s: b, c: Chain[a]): b \ ef = Chain.foldRight(f, s, c) redef head(c: Chain[a]): Option[a] = Chain.head(c) redef isEmpty(c: Chain[a]): Bool = Chain.isEmpty(c) redef memberOf(x: a, c: Chain[a]): BoolwithEq[a] = Chain.memberOf(x, c) redef forAll(f: a -> Bool \ ef, c: Chain[a]): Bool \ ef = Chain.forAll(f, c) redef exists(f: a -> Bool \ ef, c: Chain[a]): Bool \ ef = Chain.exists(f, c) }instanceUnorderedFoldable[Chain] {pubdeffoldMap(f: a -> b \ ef, c: Chain[a]): b \ efwithCommutativeMonoid[b] = Chain.foldMap(f, c) redef isEmpty(c: Chain[a]): Bool = Chain.isEmpty(c) redef exists(f: a -> Bool \ ef, c: Chain[a]): Bool \ ef = Chain.exists(f, c) redef forAll(f: a -> Bool \ ef, c: Chain[a]): Bool \ ef = Chain.forAll(f, c) redef memberOf(x: a, c: Chain[a]): BoolwithEq[a] = Chain.memberOf(x, c) }instanceTraversable[Chain] {pubdeftraverse(f: a -> m[b] \ ef, t: Chain[a]): m[Chain[b]] \ efwithApplicative[m] = Chain.traverse(f, t) redef sequence(t: Chain[m[a]]): m[Chain[a]] withApplicative[m] = Chain.sequence(t) }instanceFilterable[Chain] {pubdeffilterMap(f: a -> Option[b] \ ef, x: Chain[a]): Chain[b] \ ef = Chain.filterMap(f, x) redef filter(f: a -> Bool \ ef, x: Chain[a]): Chain[a] \ ef = Chain.filter(f, x) }instanceWitherable[Chain]instanceFormattable[Chain[a]] withFormattable[a] {typeAef = Formattable.Aef[a]pubdefformat(c: Chain[a]): RichString \ Formattable.Aef[a] =RichString.fromString("Chain#{")+RichString.join(RichString.fromString(", "), c)+RichString.fromString("}") }instanceToString[Chain[a]] withToString[a] {pubdeftoString(c: Chain[a]): String = regionrc {"Chain#{"+ (Chain.iterator(rc, c) |> Iterator.join(", ")) +"}" } }instanceCollectable[Chain[a]] {typeElm = apubdefcollect(iter: Iterator[a, ef, r]): Chain[a] \ { ef, r } = Iterator.toChain(iter) }instanceIterable[Chain[a]] {typeElm = apubdefiterator(rc: Region[r], c: Chain[a]): Iterator[a, r, r] \ r = Chain.iterator(rc, c) }instanceForEach[Chain[a]] {typeElm = apubdefforEach(f: a -> Unit \ ef, c: Chain[a]): Unit \ ef = Chain.forEach(f, c) }////// A datatype for pattern matching on a chain (traversing left-to-right).///pubenumViewLeft[t] withEq {case NoneLeftcase SomeLeft(t, Chain[t]) }////// A datatype for pattern matching on a chain (traversing right-to-left).///pubenumViewRight[t] withEq {case NoneRightcase SomeRight(Chain[t], t) }////// Return the empty chain.///pubdefempty(): Chain[a] = Empty////// Return the singleton chain with element `x`.///pubdefsingleton(x: a): Chain[a] = One(x)////// Apply every function from `f` to every argument from `x` and return a chain with all results./// For `f = f1, f2, ...` and `x = x1, x2, ...` the results appear in the order/// `f1(x1), f1(x2), ..., f2(x1), f2(x2), ...`.///pubdefap(f: Chain[a -> b \ ef], x: Chain[a]): Chain[b] \ ef =defloop(g, acc) = matchg {case ViewLeft.NoneLeft => acccase ViewLeft.SomeLeft(h, xs) => loop(viewLeft(xs), acc`append`map(h, x)) };loop(viewLeft(f), empty())////// Returns true if and only if `c` is the empty chain.///pubdefisEmpty(c: Chain[a]): Bool = matchc {case Empty => truecase_ => false }////// Returns true if and only if `c` is a non-empty chain.///pubdefnonEmpty(c: Chain[a]): Bool = notisEmpty(c)////// Add element `x` to the left end of chain `c`.///pubdefcons(x: a, c: Chain[a]): Chain[a] = matchc {case Empty => One(x)case_ => Chain(One(x), c) }////// Add element `x` to the right end of chain `c`.///pubdefsnoc(c: Chain[a], x: a): Chain[a] = matchc {case Empty => One(x)case_ => Chain(c, One(x)) }////// Returns `Some(x)` if `x` is the first element of `c`.////// Returns `None` if `c` is empty.///pubdefhead(c: Chain[a]): Option[a] = matchviewLeft(c) {case ViewLeft.SomeLeft(x, _) => Some(x)case_ => None }////// Returns `Some(x)` if `x` is the last element of `c`.////// Returns `None` if `c` is empty.///pubdeflast(c: Chain[a]): Option[a] = matchviewRight(c) {case ViewRight.SomeRight(_, x) => Some(x)case_ => None }////// Returns the element at position `i` in the chain `c`.////// Throws `IndexOutOfBoundsException` if the index is out of bounds.///pubdefget(i: Int32, c: Chain[a]): a =matchnth(i, c) {case Some(x) => xcase None => indexOutOfBounds!("index ${i} is out of bounds for Chain of length ${length(c)}") }////// Optionally returns the element at position `i` in the chain `c`.///pubdefnth(i: Int32, c: Chain[a]): Option[a] =List.nth(i, toList(c))////// Returns the subchain of `c` without the last element./// Returns `None` if the chain `c` is empty.///pubdefinit(c: Chain[a]): Option[Chain[a]] = matchviewRight(c) {case ViewRight.SomeRight(rs, _) => Some(rs)case_ => None }////// Returns the number of elements in `c`.///pubdeflength(c: Chain[a]): Int32 = foldRight((_, acc) -> acc+1, 0, c)////// Returns the number of elements in `c`.///pubdefsize(c: Chain[a]): Int32 = length(c)////// Returns a new chain formed by appending the chains `c1` and `c2`.///pubdefappend(c1: Chain[a], c2: Chain[a]): Chain[a] = match (c1, c2) {case (Empty, c) => ccase (c, Empty) => ccase_ => Chain(c1, c2) }////// Deconstruct a Chain from left-to-right.////// Returns `ViewLeft(x, rs)` if the chain is non-empty, where `x` is the leftmost/// element of the chain `c`, and `rs` is the rest of the chain.////// Returns `ViewLeft.NoneLeft` if the chain is empty.///pubdefviewLeft(c: Chain[a]): ViewLeft[a] =defloop(cc, acc) = matchcc {case Empty => ViewLeft.NoneLeftcase One(x) => ViewLeft.SomeLeft(x, acc)case Chain(l, r) => loop(l, append(r, acc)) };loop(c, Empty)////// Deconstruct a Chain from right-to-left.////// Returns `ViewRight(rs, x)` if the chain is non-empty, where `x` is the rightmost/// element of the chain `c``, and `rs` is the front of the chain.////// Returns `ViewRight.NoneRight` if the chain is empty.///pubdefviewRight(c: Chain[a]): ViewRight[a] =defloop(cc, acc) = matchcc {case Empty => ViewRight.NoneRightcase One(x) => ViewRight.SomeRight(acc, x)case Chain(l, r) => loop(r, append(acc, l)) };loop(c, Empty)////// Returns `true` if and only if `c` contains the element `a`.///pubdefmemberOf(a: a, c: Chain[a]): BoolwithEq[a] = matchviewLeft(c) {case ViewLeft.NoneLeft => falsecase ViewLeft.SomeLeft(x, _) ifx==a => truecase ViewLeft.SomeLeft(_, xs) => memberOf(a, xs) }////// Optionally returns the position of `a` in `c`.///pubdefindexOf(a: a, c: Chain[a]): Option[Int32] withEq[a] =defloop(cc, i) = matchcc {case ViewLeft.NoneLeft => Nonecase ViewLeft.SomeLeft(x, xs) => if (x==a) Some(i) elseloop(viewLeft(xs), i+1) };loop(viewLeft(c), 0)////// Returns the positions of all occurrences of `x` in `c`.///pubdefindicesOf(x: a, c: Chain[a]): Vector[Int32] withEq[a] =defloop(cc, i, indices) = matchcc {case ViewLeft.NoneLeft => indicescase ViewLeft.SomeLeft(y, ys) => if (x==y) loop(viewLeft(ys), i+1, i :: indices) elseloop(viewLeft(ys), i+1, indices) };loop(viewLeft(c), 0, Nil) |> List.reverse |> List.toVector////// Returns a range of all valid indices of the chain `c`.///pubdefindices(c: Chain[a]): Range[Int32] = Range.Range(0, length(c))////// Alias for `findLeft`.////// The function `f` must be pure.///pubdeffind(f: a -> Bool, c: Chain[a]): Option[a] = findLeft(f, c)////// Optionally returns the first element of `c` that satisfies the predicate `f` when searching from left to right.////// The function `f` must be pure.///pubdeffindLeft(f: a -> Bool, c: Chain[a]): Option[a] = matchviewLeft(c) {case ViewLeft.NoneLeft => Nonecase ViewLeft.SomeLeft(x, rs) => if (f(x)) Some(x) elsefindLeft(f, rs) }////// Optionally returns the first element of `c` that satisfies the predicate `f` when searching from right to left.////// The function `f` must be pure.///pubdeffindRight(f: a -> Bool, c: Chain[a]): Option[a] = matchviewRight(c) {case ViewRight.NoneRight => Nonecase ViewRight.SomeRight(rs, x) => if (f(x)) Some(x) elsefindRight(f, rs) }////// Returns a list of all integers between `b` (inclusive) and `e` (exclusive).////// Returns an empty chain if `b >= e`.///pubdefrange(b: Int32, e: Int32): Chain[Int32] =defloop(i, acc) = if (i>=e) accelseloop(i+1, snoc(acc, i));loop(b, Chain.empty())////// Returns a chain with the element `a` repeated `n` times.////// Returns an empty chain if `n < 0`.///pubdefrepeat(n: Int32, a: a): Chain[a] =defloop(i, acc) = {if (i<=0)accelseloop(i-1, cons(a, acc)) };loop(n, Empty)////// Alias for `scanLeft`.///pubdefscan(f: (b, a) -> b \ ef, s: b, c: Chain[a]): Chain[b] \ ef = scanLeft(f, s, c)////// Accumulates the result of applying `f` to `c` going left to right.////// That is, the result is of the form: `s :: f(s, x1) :: f(f(s, x1), x2) ...`.///pubdefscanLeft(f: (b, a) -> b \ ef, s: b, c: Chain[a]): Chain[b] \ ef =defloop(cc, a, acc) = matchviewLeft(cc) {case ViewLeft.NoneLeft => acccase ViewLeft.SomeLeft(x, xs) =>letaa = f(a, x);loop(xs, aa, snoc(acc, aa)) };loop(c, s, singleton(s))////// Accumulates the result of applying `f` to `c` going right to left.////// That is, the result is of the form: `... f(xn-1, f(xn, s)) :: f(xn, s) :: s`.///pubdefscanRight(f: (a, b) -> b \ ef, s: b, c: Chain[a]): Chain[b] \ ef =defloop(cc, a, acc) = matchviewRight(cc) {case ViewRight.NoneRight => acccase ViewRight.SomeRight(xs, x) =>letaa = f(x, a);loop(xs, aa, cons(aa, acc)) };loop(c, s, singleton(s))////// Returns the result of applying `f` to every element in `c`.////// That is, the result is of the form: `f(x1) :: f(x2) :: ...`.///pubdefmap(f: a -> b \ ef, c: Chain[a]): Chain[b] \ ef =defloop(cc, acc) = matchviewLeft(cc) {case ViewLeft.NoneLeft => acccase ViewLeft.SomeLeft(a, rs) => loop(rs, snoc(acc, f(a))) };loop(c, Empty)////// Returns the result of applying `f` to every element in `c` along with that element's index.////// That is, the result is of the form: `f(0, x0) :: f(1, x1) :: ...`.///pubdefmapWithIndex(f: (Int32, a) -> b \ ef, c: Chain[a]): Chain[b] \ ef =defloop(cc, i, acc) = matchviewLeft(cc) {case ViewLeft.NoneLeft => acccase ViewLeft.SomeLeft(x, rs) =>leta = f(i, x);loop(rs, i+1, snoc(acc, a)) };loop(c, 0, Empty)////// Returns the result of applying `f` to every element in `c` and concatenating the results.///pubdefflatMap(f: a -> Chain[b] \ ef, c: Chain[a]): Chain[b] \ ef =defloop(cc, acc) = matchviewLeft(cc) {case ViewLeft.NoneLeft => acccase ViewLeft.SomeLeft(a, rs) => loop(rs, append(acc, f(a))) };loop(c, Empty)////// Returns the reverse of `c`.///pubdefreverse(c: Chain[a]): Chain[a] =defloop(cc, acc) = matchviewLeft(cc) {case ViewLeft.NoneLeft => acccase ViewLeft.SomeLeft(a, rs) => loop(rs, cons(a, acc)) };loop(c, Empty)////// Returns `c` with `a` inserted between every two adjacent elements.///pubdefintersperse(a: a, c: Chain[a]): Chain[a] =defloop(cc, acc) = matchviewLeft(cc) {case ViewLeft.NoneLeft => acccase ViewLeft.SomeLeft(x, rs) => loop(rs, acc`snoc`a`snoc`x) };matchviewLeft(c) {case ViewLeft.NoneLeft => Emptycase ViewLeft.SomeLeft(x, rs) => loop(rs, singleton(x)) }////// Returns the number of elements in `c` that satisfy the predicate `f`.///pubdefcount(f: a -> Bool \ ef, c: Chain[a]): Int32 \ ef =defloop(cc, acc) = matchviewLeft(cc) {case ViewLeft.NoneLeft => acccase ViewLeft.SomeLeft(a, rs) => if (f(a)) loop(rs, acc+1) elseloop(rs, acc) };loop(c, 0)////// Returns the sum of all elements in the chain `c`.///pubdefsum(c: Chain[Int32]): Int32 =Foldable.sum(c)////// Returns the sum of all elements in the chain `c` according to the function `f`.///pubdefsumWith(f: a -> Int32 \ ef, c: Chain[a]): Int32 \ ef =Foldable.sumWith(f, c)////// Returns the concatenation of the elements in `c`.///pubdefflatten(c: Chain[Chain[a]]): Chain[a] =foldLeft(append, empty(), c)////// Returns `true` if and only if at least one element in `c` satisfies the predicate `f`.////// Returns `false` if `c` is empty.///pubdefexists(f: a -> Bool \ ef, c: Chain[a]): Bool \ ef = matchviewLeft(c) {case ViewLeft.NoneLeft => falsecase ViewLeft.SomeLeft(x, xs) => f(x) orexists(f, xs) }////// Returns `true` if and only if all elements in `c` satisfy the predicate `f`.////// Returns `true` if `c` is empty.///pubdefforAll(f: a -> Bool \ ef, c: Chain[a]): Bool \ ef = matchviewLeft(c) {case ViewLeft.NoneLeft => truecase ViewLeft.SomeLeft(x, xs) => f(x) andforAll(f, xs) }////// Returns a chain of every element in `c` that satisfies the predicate `f`.////// The function `f` must be pure.///pubdeffilter(f: a -> Bool \ ef, c: Chain[a]): Chain[a] \ ef =defloop(cc, acc) = matchviewLeft(cc) {case ViewLeft.NoneLeft => acccase ViewLeft.SomeLeft(a, rs) => if (f(a)) loop(rs, snoc(acc, a)) elseloop(rs, acc) };loop(c, Empty)////// Applies `f` to a start value `s` and all elements in `c` going from left to right.////// That is, the result is of the form: `f(...f(f(s, x1), x2)..., xn)`.///pubdeffoldLeft(f: (b, a) -> b \ ef, s: b, c: Chain[a]): b \ ef = matchviewLeft(c) {case ViewLeft.NoneLeft => scase ViewLeft.SomeLeft(x, xs) => foldLeft(f, f(s, x), xs) }////// Applies `f` to a start value `s` and all elements in `c` going from right to left.////// That is, the result is of the form: `f(x1, ...f(xn-1, f(xn, s))...)`.///pubdeffoldRight(f: (a, b) -> b \ ef, s: b, c: Chain[a]): b \ ef = matchviewRight(c) {case ViewRight.NoneRight => scase ViewRight.SomeRight(xs, x) => foldRight(f, f(x, s), xs) }////// Returns the result of mapping each element and combining the results.///pubdeffoldMap(f: a -> b \ ef, c: Chain[a]): b \ efwithMonoid[b] =foldLeft((acc, x) -> Monoid.combine(acc, f(x)), Monoid.empty(), c)////// Returns `c` without the first `n` elements.////// Returns an empty chain if `n > length(c)`./// Returns `c` if `n < 0`.///pubdefdropLeft(n: Int32, c: Chain[a]): Chain[a] =if (n<=0)celsematchviewLeft(c) {case ViewLeft.NoneLeft => Emptycase ViewLeft.SomeLeft(_, xs) => dropLeft(n-1, xs) }////// Returns `c` without the last `n` elements.////// Returns an empty chain if `n > length(c)`./// Returns `c` if `n < 0`.///pubdefdropRight(n: Int32, c: Chain[a]): Chain[a] =if (n<=0)celsematchviewRight(c) {case ViewRight.NoneRight => Emptycase ViewRight.SomeRight(xs, _) => dropRight(n-1, xs) }////// Returns `c` without the longest prefix that satisfies the predicate `f`.///pubdefdropWhileLeft(f: a -> Bool \ ef, c: Chain[a]): Chain[a] \ ef = matchviewLeft(c) {case ViewLeft.SomeLeft(x, xs) => if (f(x)) dropWhileLeft(f, xs) elseccase ViewLeft.NoneLeft => c }////// Returns `c` without the longest suffix that satisfies the predicate `f`.///pubdefdropWhileRight(f: a -> Bool \ ef, c: Chain[a]): Chain[a] \ ef = matchviewRight(c) {case ViewRight.SomeRight(xs, x) => if (f(x)) dropWhileRight(f, xs) elseccase ViewRight.NoneRight => c }////// Returns the first `n` elements of `c`.////// Returns `c` if `n > length(c)`./// Returns an empty chain if `n < 0`.///pubdeftakeLeft(n: Int32, c: Chain[a]): Chain[a] =defloop(cc, i, acc) = matchviewLeft(cc) {case ViewLeft.NoneLeft => acccase_ifi<1 => acccase ViewLeft.SomeLeft(a, rs) => loop(rs, i-1, snoc(acc, a)) };if (n<0) Emptyelseloop(c, n, Empty)////// Returns the last `n` elements of `c`.////// Returns `c` if `n > length(c)`./// Returns an empty chain if `n < 0`.///pubdeftakeRight(n: Int32, c: Chain[a]): Chain[a] =defloop(cc, i, acc) = matchviewRight(cc) {case ViewRight.NoneRight => acccase_ifi<1 => acccase ViewRight.SomeRight(rs, a) => loop(rs, i-1, cons(a, acc)) };if (n<0) Emptyelseloop(c, n, Empty)////// Returns the longest prefix of `c` that satisfies the predicate `f`.///pubdeftakeWhileLeft(f: a -> Bool \ ef, c: Chain[a]): Chain[a] \ ef =defloop(cc, acc) = matchviewLeft(cc) {case ViewLeft.NoneLeft => acccase ViewLeft.SomeLeft(a, rs) => if (f(a)) loop(rs, snoc(acc, a)) elseacc };loop(c, Empty)////// Returns the longest suffix of `c` that satisfies the predicate `f`.///pubdeftakeWhileRight(f: a -> Bool \ ef, c: Chain[a]): Chain[a] \ ef =defloop(cc, acc) = matchviewRight(cc) {case ViewRight.NoneRight => acccase ViewRight.SomeRight(rs, a) => if (f(a)) loop(rs, cons(a, acc)) elseacc };loop(c, Empty)////// Collects the results of applying the partial function `f` to every element in `c`.///pubdeffilterMap(f: a -> Option[b] \ ef, c: Chain[a]): Chain[b] \ ef =letstep = (acc, x) -> matchf(x) {case None => acccase Some(v) => snoc(acc, v) };foldLeft(step, empty(), c)////// Returns the first non-None result of applying the partial function `f` to each element of `c`.////// Returns `None` if every element of `c` is `None`.///pubdeffindMap(f: a -> Option[b] \ ef, c: Chain[a]): Option[b] \ ef = matchviewLeft(c) {case ViewLeft.NoneLeft => Nonecase ViewLeft.SomeLeft(x, xs) =>matchf(x) {case None => findMap(f, xs)case Some(v) => Some(v) } }////// Returns a chain where the element at index `i` is `(a, b)` where/// `a` is the element at index `i` in `c1` and `b` is the element at index `i` in `c2`.////// If either `c1` or `c2` becomes depleted, then no further elements are added to the resulting chain.///pubdefzip(c1: Chain[a], c2: Chain[b]): Chain[(a, b)] =defloop(cc1, cc2, acc) = match (viewLeft(cc1), viewLeft(cc2)) {case (ViewLeft.SomeLeft(a, rs), ViewLeft.SomeLeft(b, qs)) => loop(rs, qs, snoc(acc, (a, b)))case_ => acc };loop(c1, c2, empty())////// Returns a chain where the element at index `i` is `f(a, b)` where/// `a` is the element at index `i` in `c1` and `b` is the element at index `i` in `c2`.////// If either `c1` or `c2` becomes depleted, then no further elements are added to the resulting chain.///pubdefzipWith(f: (a, b) -> c \ ef, c1: Chain[a], c2: Chain[b]): Chain[c] \ ef =defloop(cc1, cc2, acc) = match (viewLeft(cc1), viewLeft(cc2)) {case (ViewLeft.SomeLeft(a, rs), ViewLeft.SomeLeft(b, qs)) => loop(rs, qs, snoc(acc, f(a, b)))case_ => acc };loop(c1, c2, empty())////// Generalize `zipWith` to an applicative functor `f`.///pubdefzipWithA(f: (a, b) -> m[c] \ ef, xs: Chain[a], ys: Chain[b]): m[Chain[c]] \ efwithApplicative[m] =use Functor.{<$>};use Applicative.{<*>, point};defloop(v1, v2, k) = match (v1, v2) {case (ViewLeft.SomeLeft(x, c1), ViewLeft.SomeLeft(y, c2)) => loop(viewLeft(c1), viewLeft(c2), ks -> k(cons <$> f(x, y) <*> ks))case (_, _) => k(point(empty())) };loop(viewLeft(xs), viewLeft(ys), x -> checked_ecast(x))////// Returns a pair of chains, the first containing all first components in `c`/// and the second containing all second components in `c`.///pubdefunzip(c: Chain[(a, b)]): (Chain[a], Chain[b]) =defloop(cc, acc1, acc2) = matchviewLeft(cc) {case ViewLeft.NoneLeft => (acc1, acc2)case ViewLeft.SomeLeft((a, b), rs) => loop(rs, snoc(acc1, a), snoc(acc2, b)) };loop(c, Chain.empty(), Chain.empty())////// `mapAccumLeft` is a stateful version of `map`. The accumulating parameter `s` is updated at each/// step in a left-to-right traversal.///pubdefmapAccumLeft(f: (s, a) -> (s, b) \ ef, start: s, c: Chain[a]): (s, Chain[b]) \ ef =defloop(cc, s1, acc) = matchviewLeft(cc) {case ViewLeft.NoneLeft => (s1, acc)case ViewLeft.SomeLeft(a, rs) => {let (s2, b) = f(s1, a);loop(rs, s2, snoc(acc, b)) } };loop(c, start, Empty)////// `mapAccumRight` is a stateful version of `map`. The accumulating parameter `s` is updated at each/// step in a right-to-left traversal.///pubdefmapAccumRight(f: (s, a) -> (s, b) \ ef, start: s, c: Chain[a]): (s, Chain[b]) \ ef =defloop(cc, s1, acc) = matchviewRight(cc) {case ViewRight.NoneRight => (s1, acc)case ViewRight.SomeRight(rs, a) => {let (s2, b) = f(s1, a);loop(rs, s2, cons(b, acc)) } };loop(c, start, Empty)////// Applies `f` to every element of `c`.///pubdefforEach(f: a -> Unit \ ef, c: Chain[a]): Unit \ ef = matchviewLeft(c) {case ViewLeft.NoneLeft => ()case ViewLeft.SomeLeft(x, xs) => f(x); forEach(f, xs) }////// Applies `f` to every element of `c` along with that element's index.///pubdefforEachWithIndex(f: (Int32, a) -> Unit \ ef, c: Chain[a]): Unit \ ef =defloop(cc, i) = matchcc {case ViewLeft.NoneLeft => ()case ViewLeft.SomeLeft(x, xs) => f(i, x); loop(viewLeft(xs), i+1) };loop(viewLeft(c), 0)////// Returns `c` as a list.///pubdeftoList(c: Chain[a]): List[a] =foldRight((x, acc) -> x :: acc, Nil, c)////// Returns the list `c` as a set.///pubdeftoSet(c: Chain[a]): Set[a] withOrder[a] =foldRight(Set.insert, Set.empty(), c)////// Returns the chain of pairs `c` that represents an association list as a map.////// If `c` contains multiple mappings with the same key, `toMap` does not/// make any guarantees about which mapping will be in the resulting map.///pubdeftoMap(c: Chain[(a, b)]): Map[a, b] withOrder[a] =foldRight((x, acc) -> Map.insert(fst(x), snd(x), acc), Map.empty(), c)////// Returns the chain `c` as an array.///pubdeftoArray(rc: Region[r], c: Chain[a]): Array[a, r] \ r = matchhead(c) {case None => Array#{} @ rccase Some(_) =>letarr = Array.empty(rc, length(c));forEach(match (i, b) -> Array.put(b, i, arr), zipWithIndex(c));arr }////// Returns the chain `c` as a vector.///pubdeftoVector(c: Chain[a]): Vector[a] = regionrc {letarr = Array.empty(rc, length(c));forEachWithIndex((i, x) -> Array.put(x, i, arr), c);Array.toVector(arr) }////// Returns an iterator over `c`.///pubdefiterator(rc: Region[r], c: Chain[a]): Iterator[a, r, r] \ r =letcursor = Ref.fresh(rc, viewLeft(c));letnext = () -> match (Ref.get(cursor)) {case ViewLeft.NoneLeft => Nonecase ViewLeft.SomeLeft(x, xs) =>Ref.put(viewLeft(xs), cursor); Some(x) };Iterator.unfoldWithIter(rc, next)////// Returns the chain `c` as a Nel.///pubdeftoNel(c: Chain[a]): Option[Nel[a]] =matchviewLeft(c) {case ViewLeft.NoneLeft => Nonecase ViewLeft.SomeLeft(x, rs) => Nel.Nel(x, Chain.toList(rs)) |> Some }////// Returns the chain `c` as a Nec.///pubdeftoNec(c: Chain[a]): Option[Nec[a]] =matchviewLeft(c) {case ViewLeft.NoneLeft => Nonecase ViewLeft.SomeLeft(x, rs) => foldLeft(Nec.snoc, Nec.singleton(x), rs) |> Some }////// Returns `true` if and only if `c1` and `c2` and equal.///pubdefequals(c1: Chain[a], c2: Chain[a]): BoolwithEq[a] =// Note: Chains are considered equal if their (ordered) list of elements are equal.// Because they may have different shapes due to construction we use a view to// decide equality which imposes an order on the Chain.match (viewLeft(c1), viewLeft(c2)) {case (ViewLeft.NoneLeft, ViewLeft.NoneLeft) => truecase (ViewLeft.SomeLeft(x, xs), ViewLeft.SomeLeft(y, ys)) if (x==y) => equals(xs, ys)case_ => false }////// Compares chains `c1` and `c2` lexicographically.///pubdefcompare(c1: Chain[a], c2: Chain[a]): ComparisonwithOrder[a] =defloop(cc1, cc2) = match (cc1, cc2) {case (SomeLeft(_, _), NoneLeft) => Comparison.GreaterThancase (NoneLeft, NoneLeft) => Comparison.EqualTocase (NoneLeft, SomeLeft(_, _)) => Comparison.LessThancase (SomeLeft(l, ls), SomeLeft(r, rs)) =>match (l<=>r) {case Comparison.EqualTo => loop(viewLeft(ls), viewLeft(rs))casecmp => cmp } };loop(viewLeft(c1), viewLeft(c2))////// Sort chain `c` so that elements are ordered from low to high according to their `Order` instance.////// The sort is not stable, i.e., equal elements may appear in a different order than in the input `c`.////// The sort implementation is a Quicksort.///pubdefsort(c: Chain[a]): Chain[a] withOrder[a] = regionrc {toArray(rc, c) !> Array.sort |> Array.toChain }/// Sort chain `c` so that elements are ordered from low to high according to the `Order` instance/// for the values obtained by applying `f` to each element.////// The sort is not stable, i.e., equal elements may appear in a different order than in the input `c`.////// The sort implementation is a Quicksort.///pubdefsortBy(f: a -> b, c: Chain[a]): Chain[a] withOrder[b] = regionrc {toArray(rc, c) !> Array.sortBy(f) |> Array.toChain }////// Sort chain `c` so that elements are ordered from low to high according to the comparison function `cmp`.////// The sort is not stable, i.e., equal elements may appear in a different order than in the input `c`.////// The sort implementation is a Quicksort.///pubdefsortWith(cmp: (a, a) -> Comparison, c: Chain[a]): Chain[a] = regionrc {toArray(rc, c) !> Array.sortWith(cmp) |> Array.toChain }////// Helper function for `traverse` and `sequence`.////// Builds an "applicative chain" from an applicative chain of the front of the chain/// "snocing" a last element of one applictive action.///defsnocA(mxs: f[Chain[a]], mx: f[a]): f[Chain[a]] withApplicative[f] = (((xs, x) -> snoc(xs, x)) `Functor.map`mxs) `Applicative.ap`mx////// Returns the result of running all the actions in the chain `c`.///pubdefsequence(c: Chain[m[a]]): m[Chain[a]] withApplicative[m] =defloop(cc, acc) = matchcc {case ViewLeft.NoneLeft => acccase ViewLeft.SomeLeft(x, rs) => loop(viewLeft(rs), snocA(acc, x)) };loop(viewLeft(c), Applicative.point(empty()))////// Returns the result of applying the applicative mapping function `f` to all the elements of the/// chain `c`.///pubdeftraverse(f: a -> m[b] \ ef, c: Chain[a]): m[Chain[b]] \ efwithApplicative[m] =defloop(cc, acc) = matchcc {case ViewLeft.NoneLeft => acccase ViewLeft.SomeLeft(x, rs) => loop(viewLeft(rs), snocA(acc, f(x))) };loop(viewLeft(c), Applicative.point(empty()))////// Returns the concatenation of the string representation/// of each element in `c` with `sep` inserted between each element.///pubdefjoin(sep: String, c: Chain[a]): StringwithToString[a] =Foldable.join(sep, c)////// Returns the concatenation of the string representation/// of each element in `c` according to `f` with `sep` inserted between each element.///pubdefjoinWith(f: a -> String \ ef, sep: String, c: Chain[a]): String \ ef =Foldable.joinWith(f, sep, c)////// Returns a chain where each element `e` is mapped to `(i, e)` where `i`/// is the index of `e`.///pubdefzipWithIndex(c: Chain[a]): Chain[(Int32, a)] =defloop(cc, i, acc) = matchviewLeft(cc) {case ViewLeft.NoneLeft => acccase ViewLeft.SomeLeft(a, rs) => loop(rs, i+1, snoc(acc, (i, a))) };loop(c, 0, Empty)////// Shuffles `c` using the Fisher–Yates shuffle.///pubdefshuffle(c: Chain[a]): Chain[a] \ Shuffle = regionrc {toArray(rc, c) !> Array.shuffle |> Array.toChain }}