/* * Copyright 2023 Magnus Madsen, Stephen Tetley * * Use of this source code is governed by the Apache 2.0 license * that can be found in the LICENSE.md file. */////// A Vector data type which is fundamentally like Array but is immutable.///instanceIndexable[Vector[a]] {typeIdx = Int32typeElm = atypeAef = OutOfBoundspubdefget(t: Vector[a], i: Int32): a \ OutOfBounds = {if (0<=iandi<Vector.length(t))Vector.get(i, t)elseOutOfBounds.outOfBounds("index ${i} is out of bounds for Vector of length ${Vector.length(t)}") }}instanceToString[Vector[a]] withToString[a] {pubdeftoString(v: Vector[a]): String = Vector.toString(v)}instanceFormattable[Vector[a]] withFormattable[a] {typeAef = Formattable.Aef[a]pubdefformat(x: Vector[a]): RichString \ Formattable.Aef[a] =use RichString.{fromString, joinWith};fromString("Vector#{") +joinWith(Formattable.format, fromString(", "), Vector.toList(x)) +fromString("}")}instanceHash[Vector[a]] withHash[a] {pubdefhash(v: Vector[a]): Int32 =Vector.foldLeft((acc, x) -> acc`Hash.combine`Hash.hash(x), Hash.magic(), v)}instanceEq[Vector[a]] withEq[a] {pubdefeq(v1: Vector[a], v2: Vector[a]): Bool = Vector.equals(v1, v2)}instanceOrder[Vector[a]] withOrder[a] {pubdefcompare(v1: Vector[a], v2: Vector[a]): Comparison = Vector.compare(v1, v2)}instanceFunctor[Vector] {pubdefmap(f: a -> b \ ef, v: Vector[a]): Vector[b] \ ef = Vector.map(f, v)}instanceApplicative[Vector] {pubdefpoint(a: a): Vector[a] = Vector.singleton(a)pubdefap(f: Vector[a -> b \ ef], v: Vector[a]): Vector[b] \ ef = Vector.ap(f, v)}instanceMonad[Vector] {pubdefflatMap(f: a -> Vector[b] \ ef, v: Vector[a]): Vector[b] \ ef = Vector.flatMap(f, v)}instanceMonadZero[Vector] {pubdefempty(): Vector[a] = Vector.empty()}instanceMonadZip[Vector] {pubdefzipWith(f: (a, b) -> c \ ef, xs: Vector[a], ys: Vector[b]): Vector[c] \ ef = Vector.zipWith(f, xs, ys)pubdefzipWithA(f: (a, b) -> f[c] \ ef, xs: Vector[a], ys: Vector[b]): f[Vector[c]] \ efwithApplicative[f] = Vector.zipWithA(f, xs, ys) redef zip(v1: Vector[a], v2: Vector[b]): Vector[(a, b)] = Vector.zip(v1, v2) redef unzip(v: Vector[(a, b)]): (Vector[a], Vector[b]) = Vector.unzip(v)}instanceFoldable[Vector] {pubdeffoldLeft(f: (b, a) -> b \ ef, s: b, v: Vector[a]): b \ ef = Vector.foldLeft(f, s, v)pubdeffoldRight(f: (a, b) -> b \ ef, s: b, v: Vector[a]): b \ ef = Vector.foldRight(f, s, v) redef head(v: Vector[a]): Option[a] = Vector.head(v) redef isEmpty(v: Vector[a]): Bool = Vector.isEmpty(v) redef memberOf(x: a, v: Vector[a]): BoolwithEq[a] = Vector.memberOf(x, v) redef forAll(f: a -> Bool \ ef, v: Vector[a]): Bool \ ef = Vector.forAll(f, v) redef exists(f: a -> Bool \ ef, v: Vector[a]): Bool \ ef = Vector.exists(f, v)}instanceUnorderedFoldable[Vector] {pubdeffoldMap(f: a -> b \ ef, v: Vector[a]): b \ efwithCommutativeMonoid[b] = Vector.foldMap(f, v) redef isEmpty(v: Vector[a]): Bool = Vector.isEmpty(v) redef exists(f: a -> Bool \ ef, v: Vector[a]): Bool \ ef = Vector.exists(f, v) redef forAll(f: a -> Bool \ ef, v: Vector[a]): Bool \ ef = Vector.forAll(f, v) redef memberOf(x: a, v: Vector[a]): BoolwithEq[a] = Vector.memberOf(x, v)}instanceTraversable[Vector] {pubdeftraverse(f: a -> m[b] \ ef, t: Vector[a]): m[Vector[b]] \ efwithApplicative[m] = Vector.traverse(f, t) redef sequence(t: Vector[m[a]]): m[Vector[a]] withApplicative[m] = Vector.sequence(t)}instanceFilterable[Vector] {pubdeffilterMap(f: a -> Option[b] \ ef, x: Vector[a]): Vector[b] \ ef = Vector.filterMap(f, x) redef filter(f: a -> Bool \ ef, x: Vector[a]): Vector[a] \ ef = Vector.filter(f, x)}instanceWitherable[Vector]instanceSemiGroup[Vector[a]] {pubdefcombine(x: Vector[a], y: Vector[a]): Vector[a] = Vector.append(x, y)}instanceMonoid[Vector[a]] {pubdefempty(): Vector[a] = Vector.empty()}instanceCollectable[Vector[a]] {typeElm = apubdefcollect(iter: Iterator[a, ef, r]): Vector[a] \ (ef + r) = Iterator.toVector(iter)}instanceIterable[Vector[a]] {typeElm = apubdefiterator(rc: Region[r], v: Vector[a]): Iterator[a, r, r] \ r = Vector.iterator(rc, v)}instanceForEach[Vector[a]] {typeElm = apubdefforEach(f: a -> Unit \ ef, v: Vector[a]): Unit \ ef = Vector.forEach(f, v)}pubmod Vector {use Math.Shuffle////// Perform a binary search for `x` on the sorted vector `v` and returns the position of `x`.////// Returns `None` if `v` does not contain `x`. Otherwise returns `Some(i)`,/// where `Vector.get(i, v) == x`.////// Assumes `v` is sorted. If this is not the case the result is undefined.////// If `v` contains multiple `x`-values then the index of one of them will be returned.///pubdefbinarySearch(x: a, v: Vector[a]): Option[Int32] withOrder[a] =deff(l, r) = {if (l<=r) {letm = (l+r) `Int32.rightShift`1; // Shifting by 1 is slightly faster than dividing by 2.matchget(m, v) <=>x {case Comparison.LessThan => f(m+1, r)case Comparison.GreaterThan => f(l, m-1)case Comparison.EqualTo => Some(m) } } else None };letlen = length(v);f(0, len-1)////// Compares `a` and `b` lexicographically.///pubdefcompare(a: Vector[a], b: Vector[a]): ComparisonwithOrder[a] =letlen = Int32.min(length(a), length(b));defloop(i) = {if (i<len) {letcmp = get(i, a) <=>get(i, b);if (cmp== Comparison.EqualTo)loop(i+1)elsecmp } elseif (i<length(a)) { Comparison.GreaterThan } elseif (i<length(b)) { Comparison.LessThan } else { Comparison.EqualTo } };loop(0)////// Returns a string representation of the given vector `v`.///pubdeftoString(v: Vector[a]): StringwithToString[a] = regionrc {"Vector#{"+ (Vector.iterator(rc, v) |> Iterator.join(", ")) +"}" }////// Version of `Array.updateSequence` where sub is a vector rather than an array,/// so a extra copy of `sub` is avoided.///defarrayUpdateSeqV(i: Int32, sub: Vector[a], arr: Array[a, r]): Unit \ r =letend = Array.length(arr);letsubLen = length(sub);defloop(ri, wi) = {if (wi>=endorri>=subLen)()elseif (wi<0)loop(ri+1, wi+1)else {letx = get(ri, sub);Array.put(x, wi, arr);loop(ri+1, wi+1) } };loop(0, i)////// Returns an empty (length zero) vector.///pubdefempty(): Vector[a] = regionrc {letarr = Array#{} @ rc;Array.toVector(arr) }////// Returns a singleton vector containing `x``.///pubdefsingleton(x: a): Vector[a] =init(_ -> x, 1)////// Retrieves the value at position `i` in the vector `v`.///pubdefget(i: Int32, v: Vector[a]): a = %%VECTOR_GET%%(v, i)////// Optionally returns the element at position `i` in the vector `v`.///pubdefnth(i: Int32, v: Vector[a]): Option[a] =if (0<=iandi<length(v)) Some(get(i, v))else None////// Returns `true` if the given vector `v` is empty.///pubdefisEmpty(v: Vector[a]): Bool = length(v) ==0////// Returns `true` if the given vector `v` is non-empty.///pubdefnonEmpty(v: Vector[a]): Bool = notisEmpty(v)////// Returns the number of elements in the vector `v`.///pubdeflength(v: Vector[a]): Int32 = %%VECTOR_LENGTH%%(v)////// Returns the number of elements in the vector `v`.///pubdefsize(v: Vector[a]): Int32 = length(v)////// Returns a fresh array with the elements from the vector `v` from index `b` (inclusive) until index `e` (exclusive).///pubdefslice(start: {start = Int32}, end: {end = Int32}, v: Vector[a]): Vector[a] = regionrc {letarr = toArray(rc, v);Array.slice(rc, start, end, arr) |> Array.toVector }////// Returns the vector `v` as an array.///pubdeftoArray(rc: Region[r], v: Vector[a]): Array[a, r] \ r =letarr = Array.empty(rc, length(v));forEachWithIndex((i, x) -> Array.put(x, i, arr), v);arr////// Returns the vector `v` as a list.///pubdeftoList(v: Vector[a]): List[a] =foldRight((x, acc) -> x :: acc, Nil, v)////// Optionally returns the vector `v` as a non-empty list.////// If `v` is empty return `None`, otherwise return the Nel wrapped in `Some`.///pubdeftoNel(v: Vector[a]): Option[Nel[a]] =letstep = (x, acc) -> matchacc {case None => Some(Nel.singleton(x))case Some(c) => Some(Nel.cons(x, c)) };foldRight(step, None, v)////// Returns the vector `v` as a chain.///pubdeftoChain(v: Vector[a]): Chain[a] =foldRight(Chain.cons, Chain.empty(), v)////// Optionally returns the vector `v` as a non-empty chain.////// If `v` is empty return `None`, otherwise return the Nec wrapped in `Some`.///pubdeftoNec(v: Vector[a]): Option[Nec[a]] =letstep = (x, acc) -> matchacc {case None => Some(Nec.singleton(x))case Some(c) => Some(Nec.cons(x, c)) };foldRight(step, None, v)////// Returns `Some(x)` if `x` is the first element of `v`.////// Returns `None` if `v` is empty.///pubdefhead(v: Vector[a]): Option[a] =nth(0, v)////// Returns `Some(x)` if `x` is the last element of `v`.////// Returns `None` if `v` is empty.///pubdeflast(v: Vector[a]): Option[a] =nth(length(v) -1, v)////// Return a new vector, appending the elements `v2` after elements of `v1`.///pubdefappend(v1: Vector[a], v2: Vector[a]): Vector[a] = regionrc {letarr = Array.empty(rc, length(v1) +length(v2));arrayUpdateSeqV(0, v1, arr);arrayUpdateSeqV(length(v1), v2, arr);Array.toVector(arr) }////// Returns `true` if and only if `v` contains the element `x`.///pubdefmemberOf(x: a, v: Vector[a]): BoolwithEq[a] =exists(y -> y==x, v)////// Optionally finds the smallest element of `v` according to the `Order` on `v`.////// Returns `None` if `v` is empty.///pubdefminimum(v: Vector[a]): Option[a] withOrder[a] =reduceLeft(Order.min, v)////// Optionally finds the smallest element of `v` according to the given comparator `cmp`.////// Returns `None` if `v` is empty.///pubdefminimumBy(cmp: (a, a) -> Comparison, v: Vector[a]): Option[a] =reduceLeft(Order.minBy(cmp), v)////// Optionally finds the largest element of `v` according to the `Order` on `v`.////// Returns `None` if `v` is empty.///pubdefmaximum(v: Vector[a]): Option[a] withOrder[a] =reduceLeft(Order.max, v)////// Optionally finds the largest element of `v` according to the given comparator `cmp`.////// Returns `None` if `v` is empty.///pubdefmaximumBy(cmp: (a, a) -> Comparison, v: Vector[a]): Option[a] =reduceLeft(Order.maxBy(cmp), v)////// Alias for `indexOfLeft`///pubdefindexOf(x: a, v: Vector[a]): Option[Int32] withEq[a] =indexOfLeft(x, v)////// Optionally returns the position of the first occurrence of `a` in `v`/// searching from left to right.///pubdefindexOfLeft(a: a, v: Vector[a]): Option[Int32] withEq[a] =defloop(i) = {if (i>=length(v)) -1elseif (get(i, v) ==a)ielseloop(i+1) };leti = loop(0);if (i<0) None else Some(i)////// Optionally returns the position of the first occurrence of `a` in `v`/// searching from right to left.///pubdefindexOfRight(a: a, v: Vector[a]): Option[Int32] withEq[a] =defloop(i) = {if (i<0) -1elseif (get(i, v) ==a)ielseloop(i-1) };leti = loop(length(v) -1);if (i<0) None else Some(i)////// Return the positions of the all the occurrences of `a` in `v`.///pubdefindicesOf(a: a, v: Vector[a]): Vector[Int32] withEq[a] =findIndices(b -> a==b, v)////// Returns a range of all valid indices of the vector `v`.///pubdefindices(v: Vector[a]): Range[Int32] = Range.Range(0, length(v))////// Alias for `findLeft`.///pubdeffind(f: a -> Bool \ ef, v: Vector[a]): Option[a] \ ef =findLeft(f, v)////// Optionally returns the first element of `v` that satisfies the predicate `f` when searching from left to right.///pubdeffindLeft(f: a -> Bool \ ef, v: Vector[a]): Option[a] \ ef =matchfindIndexOfLeft(f, v) {case None => Nonecase Some(i) => Some(get(i, v)) }////// Optionally returns the first element of `v` that satisfies the predicate `f` when searching from right to left.///pubdeffindRight(f: a -> Bool \ ef, v: Vector[a]): Option[a] \ ef =matchfindIndexOfRight(x -> f(x), v) {case None => Nonecase Some(i) => Some(get(i, v)) }////// Returns a vector of all integers between `b` (inclusive) and `e` (exclusive).////// Returns an empty vector if `b >= e`.///pubdefrange(b: Int32, e: Int32): Vector[Int32] =letlen = e-b;init(ix -> b+ix, len)////// Returns `v` without adjacent duplicates according to their `Eq` instance.////// The first occurence in a chain of duplicates is kept.///pubdefremoveAdjDups(v: Vector[a]): Vector[a] withEq[a] = removeAdjDupsWith(Eq.eq, v)////// Returns `v` without adjacent duplicates according to the function `f`./// Elements `x` and `y` are duplicates if and only if `f(x, y) = true`.////// The first occurence in a chain of duplicates is kept.////// `f` must define an equivalence relation on the elements of the list.///pubdefremoveAdjDupsWith(f: a -> a -> Bool \ ef, v: Vector[a]): Vector[a] \ ef = regionrc {if (Vector.length(v) ==0) {v } else {letl = MutList.empty(rc);// We handle the first element twice.MutList.push(Vector.get(0, v), l);discard { (Vector.get(0, v), v) ||> Vector.foldLeft(head -> cur -> {if (f(head, cur)) {head } else {MutList.push(cur, l);cur } } ) };MutList.toVector(l) } }////// Returns a vector with the element `x` repeated `n` times.////// Returns an empty vector if `n <= 0`.///pubdefrepeat(n: Int32, x: a): Vector[a] =init(_ -> x, n)////// Alias for `scanLeft`.///pubdefscan(f: (b, a) -> b \ ef, s: b, v: Vector[a]): Vector[b] \ ef =scanLeft(f, s, v)////// Accumulates the result of applying `f` to `v` 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, v: Vector[a]): Vector[b] \ ef = regionrc {letarr = Array.empty(rc, length(v) +1);letacc = Ref.fresh(rc, s);Array.put(s, 0, arr);letstep = (i, x) -> {lets1 = f(Ref.get(acc), x);Ref.put(s1, acc);Array.put(s1, i+1, arr) };forEachWithIndex(step, v);Array.toVector(arr) }////// Accumulates the result of applying `f` to `xs` 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, v: Vector[a]): Vector[b] \ ef = regionrc {letlen = length(v);letarr = Array.empty(rc, len+1);letacc = Ref.fresh(rc, s);Array.put(s, len, arr);defloop(i) = {if (i<0)()else {lets1 = f(get(i, v), Ref.get(acc));Ref.put(s1, acc);Array.put(s1, i, arr);loop(i-1) } };loop(len-1);Array.toVector(arr) }////// Returns the result of applying `f` to every element in `v`.////// The result is a new vector.///pubdefmap(f: a -> b \ ef, v: Vector[a]): Vector[b] \ ef =init(i -> f(get(i, v)), length(v))////// Returns the result of applying `f` to every element in `v` along with that element's index.////// That is, the result is of the form: `[ f(0, a[0]), f(1, a[1]), ... ]`.///pubdefmapWithIndex(f: (Int32, a) -> b \ ef, v: Vector[a]): Vector[b] \ ef =init(i -> f(i, get(i, v)), length(v))////// Returns the result of running all the actions in the list `v` going from left/// to right.///pubdefsequence(v: Vector[m[a]]): m[Vector[a]] withApplicative[m] = regionrc {letlen = length(v);letarr = Array.empty(rc, len);defloop(i, k) = {if (i==len)k(Applicative.point(arr))else {letmx = get(i, v);loop(i+1, karr -> k(putA(mx, i, karr))) } };Functor.map(Array.toVector, loop(0, x -> checked_ecast(x))) }////// Returns the result of applying the applicative mapping function `f` to all the elements of the/// vector `v` going from left to right.///pubdeftraverse(f: a -> m[b] \ ef, v: Vector[a]): m[Vector[b]] \ efwithApplicative[m] = regionrc {letlen = length(v);letarr = Array.empty(rc, len);defloop(i, k) = {if (i==len)k(Applicative.point(arr))else {letx = get(i, v);loop(i+1, karr -> k(putA(f(x), i, karr))) } };Functor.map(Array.toVector, loop(0, x -> checked_ecast(x))) }////// Helper for `sequence`, `traverse` and `zipWithA`.///defputA(mx: m[a], i: Int32, marr: m[Array[a, r]]): m[Array[a, r]] \ rwithApplicative[m] =use Functor.{<$>};use Applicative.{<*>}; (((x, arr) -> { Array.put(x, i, arr); arr }) <$> mx) <*> marr////// Generalize `zipWith` to an applicative functor `f`.///pubdefzipWithA(f: (a, b) -> m[c] \ ef, v1: Vector[a], v2: Vector[b]): m[Vector[c]] \ efwithApplicative[m] = regionrc {letlen = Int32.min(length(v1), length(v2));letarr = Array.empty(rc, len);defloop(i, k) = {if (i==len)k(Applicative.point(arr))else {letx = get(i, v1);lety = get(i, v2);loop(i+1, karr -> k(putA(f(x, y), i, karr))) } };Functor.map(Array.toVector, loop(0, x -> checked_ecast(x))) }////// Apply every function from `f` to every argument from `v` and return a list 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: Vector[a -> b \ ef], v: Vector[a]): Vector[b] \ ef =map(g -> map(g, v), f) |> flatten////// Returns the result of applying `f` to every element in `v` and concatenating the results.///pubdefflatMap(f: a -> Vector[b] \ ef, v: Vector[a]): Vector[b] \ ef =init(i -> f(get(i, v)), length(v)) |> flatten////// Returns the reverse of `v`.///pubdefreverse(v: Vector[a]): Vector[a] =letlen = length(v);init(ix -> get(len- (ix+1), v), len)////// Rotate the contents of vector `v` by `n` steps to the left.///pubdefrotateLeft(n: Int32, v: Vector[a]): Vector[a] =letlen = length(v);if (len<1)empty()elseif (n<0)rotateRightHelper(Int32.abs(n), v)elserotateLeftHelper(n, v)////// Helper function for `rotateLeft` and `rotateRight`.////// Precondition: `n` must be positive.////// This is an explicit helper to avoid code duplication.///defrotateLeftHelper(n: Int32, v: Vector[a]): Vector[a] =letlen = length(v);letf = ix -> { letreadIx = Int32.modulo(ix+n, len); get(readIx, v) };init(f, len)////// Rotate the contents of vector `v` by `n` steps to the right.///pubdefrotateRight(n: Int32, v: Vector[a]): Vector[a] =if (length(v) <1)empty()elseif (n<0)rotateLeftHelper(Int32.abs(n), v)elserotateRightHelper(n, v)////// Helper function for `rotateRight` and `rotateLeft`.////// Precondition: `n` must be positive.////// This is an explicit helper to avoid code duplication.///defrotateRightHelper(n: Int32, v: Vector[a]): Vector[a] =letlen = length(v);letf = ix -> { letreadIx = Int32.modulo(ix-n, len); get(readIx, v) };init(f, len)////// Returns a copy of `v` with the element at index `i` replaced by `x`.////// Returns a copy of `v` if `i < 0` or `i > length(xs)-1`.///pubdefupdate(i: Int32, x: a, v: Vector[a]): Vector[a] =letf = ix -> if (ix==i) xelseget(ix, v);init(f, length(v))////// Returns `b` with the `n` elements starting at index `i` replaced with the elements of `a`.////// If any of the indices `i, i+1, i+2, ... , i+n-1` are out of range in `b` then no patching is done at these indices./// If `a` becomes depleted then no further patching is done./// If patching occurs at index `i+j` in `b`, then the element at index `j` in `a` is used.///pubdefpatch(i: Int32, n: Int32, a: Vector[a], b: Vector[a]): Vector[a] =letlen1 = length(a);letsize = if (n>len1) len1elsen;letsub = slice(start = 0, end = size, a);updateSequence(i, sub, b)////// Returns a copy of `v` with `sep` inserted between every two adjacent elements.///pubdefintersperse(sep: a, v: Vector[a]): Vector[a] =letlen1 = length(v);letlen2 = len1+len1-1;letf = ix -> matchix {case 0 => get(0, v)casenifInt32.remainder(n, 2) !=0 => sepcasen => { leti = n/2; get(i, v) } };init(f, len2)////// Returns the concatenation of the elements in `vs` with the elements/// of `sep` inserted between every two adjacent elements.///pubdefintercalate(sep: Vector[a], vs: Vector[Vector[a]]): Vector[a] = regionrc {letcount = length(vs);letsepLength = length(sep);letsepCount = if (count<2) 0elsecount-1;letlen = sumLengths(vs) + (sepCount*sepLength);letpos = Ref.fresh(rc, 0);letarr = Array.empty(rc, len);letf = (i, v) -> {if (i==0) {arrayUpdateSeqV(0, v, arr);Ref.put(length(v), pos) } else {letix = Ref.get(pos);arrayUpdateSeqV(ix, sep, arr);letix1 = ix+sepLength;arrayUpdateSeqV(ix1, v, arr);Ref.put(ix1+length(v), pos) } };forEachWithIndex(f, vs);Array.toVector(arr) }////// Sum the lengths of a vector of vectors.////// Helper function for `intercalate` and `flatten`.///defsumLengths(vs: Vector[Vector[a]]): Int32 =foldLeft((acc, a) -> acc+length(a), 0, vs)////// Returns the transpose of `vs`.////// Returns a non-transposed copy of `vs` if the dimensions of the elements of `vs` are mismatched.///pubdeftranspose(vs: Vector[Vector[a]]): Vector[Vector[a]] =letilen = length(vs);if (ilen==0)empty()else {letjlen = length(get(0, vs));if (jlen==0ornonUniform(jlen, vs))// Non-transposing nested copyinit(i -> slice(start = 0, end = length(get(i, vs)), get(i, vs)), ilen)elseinit(i -> init(j -> get(i, get(j, vs)), ilen), jlen) }////// Helper function for `transpose`.///defnonUniform(l: Int32, vs: Vector[Vector[a]]): Bool =exists(x -> length(x) !=l, vs)////// Returns a copy of `v` with every occurrence of `src` replaced by `dst`.///pubdefreplace(src: {src = a}, dst: {dst = a}, v: Vector[a]): Vector[a] withEq[a] =map(e -> if (e==src#src) dst#dst elsee, v)////// Returns `true` if and only if `a` is a prefix of `b`.///pubdefisPrefixOf(a: Vector[a], b: Vector[a]): BoolwithEq[a] =letlen1 = length(a);if (len1>length(b))falseelsedefloop(i) = {if (i>=len1)trueelseif (get(i, a) !=get(i, b))falseelseloop(i+1) };loop(0)////// Returns `true` if and only if `a` is an infix of `b`.///pubdefisInfixOf(a: Vector[a], b: Vector[a]): BoolwithEq[a] =letlen1 = length(a);letlen2 = length(b);if (len1>len2)falseelseif (len1==0)trueelseisInfixOfSearch(a, b, len1, len2, 0)////// Helper function for `isInfixOf` - scan `b` to find a match with first element of `b`.////// Precondition: len1 (length of `a`) > 0///defisInfixOfSearch(a: Vector[a], b: Vector[a], len1: Int32, len2: Int32, j: Int32): BoolwithEq[a] =if (j>=len2)falseelseif (get(0, a) ==get(j, b))isInfixOfCheck(a, b, len1, len2, 1, j+1)elseisInfixOfSearch(a, b, len1, len2, j+1)////// Helper function for `isInfixOf` - `a` has started matching, scan to see if it all matches.///defisInfixOfCheck(a: Vector[a], b: Vector[a], len1: Int32, len2: Int32, i: Int32, j: Int32): BoolwithEq[a] =if (i>=len1)// `a` exhausted, so successtrueelseif (j>=len2)// `b` exhausted, `a` still trying to match, so failurefalseelseif (get(i, a) ==get(j, b))isInfixOfCheck(a, b, len1, len2, i+1, j+1)elseisInfixOfSearch(a, b, len1, len2, j+1)////// Returns `true` if and only if `a` is a suffix of `b`.///pubdefisSuffixOf(a: Vector[a], b: Vector[a]): BoolwithEq[a] =letlen1 = length(a);letlen2 = length(b);if (len1>len2)falseelsedefloop(i, j) = {if (i<0)trueelseif (get(i, a) !=get(j, b))falseelseloop(i-1, j-1) };loop(len1-1, len2-1)////// Returns the result of applying `combine` to all the elements in `v`, using `empty` as the initial value.///pubdeffold(v: Vector[a]): awithMonoid[a] = foldLeft(Monoid.combine, Monoid.empty(), v)////// Applies `f` to a start value `s` and all elements in `v` going from left to right.////// That is, the result is of the form: `f(...f(f(s, a[0]), a[1])..., xn)`.///pubdeffoldLeft(f: (b, a) -> b \ ef, s: b, v: Vector[a]): b \ ef =letlen = length(v);defloop(i, acc) = {if (i>=len)accelseloop(i+1, f(acc, get(i, v))) };loop(0, s)////// Applies `f` to a start value `s` and all elements in `v` going from right to left.////// That is, the result is of the form: `f(a[0], ...f(a[n-1], f(a[n], s))...)`.///pubdeffoldRight(f: (a, b) -> b \ ef, s: b, v: Vector[a]): b \ ef =defloop(i, acc) = {if (i<0)accelseloop(i-1, f(get(i, v), acc)) };loop(length(v) -1, s)////// Returns the result of mapping each element and combining the results.///pubdeffoldMap(f: a -> b \ ef, v: Vector[a]): b \ efwithMonoid[b] =foldLeft((acc, x) -> Monoid.combine(acc, f(x)), Monoid.empty(), v)////// Applies `f` to all elements in `v` going from left to right until a single value `v` is obtained. Returns `Some(v)`.////// Returns `None` if `v` is empty.///pubdefreduceLeft(f: (a, a) -> a \ ef, v: Vector[a]): Option[a] \ ef =letlen = length(v);defloop(i, acc) = {if (i>=len)accelseloop(i+1, f(acc, get(i, v))) };if (len==0) Noneelse Some(loop(1, get(0, v)))////// Applies `f` to all elements in `v` going from right to left until a single value `v` is obtained. Returns `Some(v)`.////// Returns `None` if `v` is empty.///pubdefreduceRight(f: (a, a) -> a \ ef, v: Vector[a]): Option[a] \ ef =letlen = length(v);defloop(i, acc) = {if (i<0)accelseloop(i-1, f(get(i, v), acc)) };if (len==0) Noneelse Some(loop(len-2, get(len-1, v)))////// Returns the number of elements in `v` that satisfy the predicate `f`.///pubdefcount(f: a -> Bool \ ef, v: Vector[a]): Int32 \ ef =foldLeft((b, x) -> if (f(x)) b+1elseb, 0, v)////// Returns the sum of all elements in the vector `v`.///pubdefsum(v: Vector[Int32]): Int32 =foldLeft((+), 0, v)////// Returns the sum of all elements in the vector `v` according to the function `f`.///pubdefsumWith(f: a -> Int32 \ ef, v: Vector[a]): Int32 \ ef =foldLeft((acc, x) -> acc+f(x), 0, v)////// Returns the concatenation of all the vectors in the vector `vs`.///pubdefflatten(vs: Vector[Vector[a]]): Vector[a] = regionrc {letlen = sumLengths(vs);letpos = Ref.fresh(rc, 0);letarr = Array.empty(rc, len);forEach(v -> {leti = Ref.get(pos);Ref.put(i+length(v), pos);arrayUpdateSeqV(i, v, arr) },vs );Array.toVector(arr) }////// Returns `true` if and only if at least one element in `v` satisfies the predicate `f`.////// Returns `false` if `v` is empty.///pubdefexists(f: a -> Bool \ ef, v: Vector[a]): Bool \ ef =letlen = length(v);defloop(i) = {if (i>=len)falseelseif (f(get(i, v)))trueelseloop(i+1) };loop(0)////// Returns `true` if and only if all elements in `v` satisfy the predicate `f`.////// Returns `true` if `v` is empty.///pubdefforAll(f: a -> Bool \ ef, v: Vector[a]): Bool \ ef =letlen = length(v);defloop(i) = {if (i>=len)trueelseif (f(get(i, v)))loop(i+1)elsefalse };loop(0)////// Returns a vector of every element in `v` that satisfies the predicate `f`.///pubdeffilter(f: a -> Bool \ ef, v: Vector[a]): Vector[a] \ ef = regionrc {letm = MutList.empty(rc);forEach(a -> if (f(a)) { MutList.push(a, m) }, v);MutList.toVector(m) }////// Returns a pair of vectors `(v1, v2)`.////// `v1` contains all elements of `v` that satisfy the predicate `f`./// `v2` contains all elements of `v` that do not satisfy the predicate `f`.///pubdefpartition(f: a -> Bool \ ef, v: Vector[a]): (Vector[a], Vector[a]) \ ef =letstep = {x -> match (a1, a2) ->if (f(x)) (x :: a1, a2) else (a1, x :: a2) };let (xs, ys) = foldRight(step, (Nil, Nil), v); (List.toVector(xs), List.toVector(ys))////// Returns a pair of vectors `(v1, v2)`.////// `v1` is the longest prefix of `v` that satisfies the predicate `f`./// `v2` is the remainder of `v`.///pubdefspan(f: a -> Bool \ ef, v: Vector[a]): (Vector[a], Vector[a]) \ ef =matchfindIndexOfLeft(x -> not (f(x)), v) {case None => (takeLeft(length(v), v), empty())case Some(i) => (takeLeft(i, v), dropLeft(i, v)) }////// Alias for `dropLeft`.///pubdefdrop(n: Int32, v: Vector[a]): Vector[a] =dropLeft(n, v)////// Returns a copy of vector `v`, dropping the first `n` elements.////// Returns an empty vector if `n > length(v)`.///pubdefdropLeft(n: Int32, v: Vector[a]): Vector[a] =letlen = length(v);if (n>len)empty()else {letstart = if (n<0) 0elsen;slice(start = start, end = len, v) }////// Returns a copy of vector `v`, dropping the last `n` elements.////// Returns an empty vector if `n > length(v)`.///pubdefdropRight(n: Int32, v: Vector[a]): Vector[a] =letlen = length(v);if (n>=len)empty()else {letend = if (n<0) lenelselen-n;slice(start = 0, end = end, v) }////// Alias for `dropWhileLeft`.///pubdefdropWhile(f: a -> Bool \ ef, v: Vector[a]): Vector[a] \ ef =dropWhileLeft(f, v)////// Returns copy of vector `v` without the longest prefix that satisfies the predicate `f`.///pubdefdropWhileLeft(f: a -> Bool \ ef, v: Vector[a]): Vector[a] \ ef =matchfindIndexOfLeft(x -> not (f(x)), v) {case None => empty()case Some(i) => dropLeft(i, v) }////// Returns copy of vector `v` without the longest suffix that satisfies the predicate `f`.///pubdefdropWhileRight(f: a -> Bool \ ef, v: Vector[a]): Vector[a] \ ef =matchfindIndexOfRight(x -> not (f(x)), v) {case None => empty()case Some(i) => slice(start = 0, end = i+1, v) }////// Alias for `takeLeft`.///pubdeftake(n: Int32, v: Vector[a]): Vector[a] =takeLeft(n, v)////// Returns a fresh vector taking first `n` elements of `v`.////// Returns a copy of `v` if `n > length(v)`.///pubdeftakeLeft(n: Int32, v: Vector[a]): Vector[a] =if (n<=0)empty()else {letlen = length(v);letend = if (n>len) lenelsen;slice(start = 0, end = end, v) }////// Returns a fresh vector taking last `n` elements of `v`.////// Returns a copy `v` if `n > length(v)`.///pubdeftakeRight(n: Int32, v: Vector[a]): Vector[a] =if (n<=0)empty()else {letlen = length(v);letstart = if (n>len) 0elselen-n;slice(start = start, end = len, v) }////// Alias for `takeWhileLeft`.///pubdeftakeWhile(f: a -> Bool \ ef, a: Vector[a]): Vector[a] \ ef =takeWhileLeft(f, a)////// Returns the longest prefix of `v` that satisfies the predicate `f`.///pubdeftakeWhileLeft(f: a -> Bool \ ef, v: Vector[a]): Vector[a] \ ef =matchfindIndexOfLeft(x -> not (f(x)), v) {case None => slice(start = 0, end = length(v), v)case Some(i) => takeLeft(i, v) }////// Returns the longest suffix of `v` that satisfies the predicate `f`.///pubdeftakeWhileRight(f: a -> Bool \ ef, v: Vector[a]): Vector[a] \ ef =matchfindIndexOfRight(x -> not (f(x)), v) {case None => slice(start = 0, end = length(v), v)case Some(i) => slice(start = i+1, end = length(v), v) }////// Split the vector `v` at the position `n` returning the left and right parts./// Position `n` is included in the right part.////// Example: `splitAt(2, Vector#{1, 2, 3, 4})` returns `(Vector#{1, 2}, Vector#{3, 4})`////// Returns `(v, Vector#{})` if `n > length(xs)`./// Returns `(Vector#{}, v)` if `n < 0`.///pubdefsplitAt(n: Int32, v: Vector[a]): (Vector[a], Vector[a]) = (Vector.take(n, v), Vector.drop(n, v))////// Partitions `v` into subvectors such that for any two elements `x` and `y` in a subvector, `f(x, y)` is true.////// A subvector is created by iterating through the remaining elements of `v` from left to right and adding an/// element to the subvector if and only if doing so creates no conflicts with the elements already in the subvector.////// The function `f` must be pure and define an equivalence relation.///pubdefgroupWith(f: (a, a) -> Bool, v: Vector[a]): Vector[Vector[a]] =letxs = toList(v);groupByHelper(f, xs, Nil) |> List.toVector////// Partitions `v` into subvectors such that for any two elements `x` and `y` in a subvector,/// if `f(x)` and `f(y)` are equal according to `Eq` on `b`.////// A subvector is created by iterating through the remaining elements of `v` from left to right and adding an/// element to the subvector if and only if doing so creates no conflicts with the elements already in the subvector.///pubdefgroupBy(f: a -> b, v: Vector[a]): Vector[Vector[a]] withEq[b] =groupWith(Eq.eq`on`f, v)////// Helper function for `groupWith`.///defgroupByHelper(f: (a, a) -> Bool, xs: List[a], ac: List[Vector[a]]): List[Vector[a]] = matchxs {case Nil => List.reverse(ac)casex :: rs =>let (r1, r2) = extractHelper(f, rs, Nel.singleton(x), Nil);groupByHelper(f, r2, r1 :: ac) }////// Helper function for `groupWith`.///defextractHelper(f: (a, a) -> Bool, xs: List[a], ps: Nel[a], ns: List[a]): (Vector[a], List[a]) = matchxs {case Nil => {leta = Nel.reverse(ps); (Nel.toVector(a), List.reverse(ns)) }casex :: rs =>if (f(x, Nel.head(ps)))extractHelper(f, rs, Nel.cons(x, ps), ns)elseextractHelper(f, rs, ps, x :: ns) }////// Returns a vector where the element at index `i` is `(x, y)` where/// `x` is the element at index `i` in `a` and `y` is the element at index `i` in `b`.////// If either `a` or `b` becomes depleted, then no further elements are added to the resulting vector.///pubdefzip(a: Vector[a], b: Vector[b]): Vector[(a, b)] =letlen = Int32.min(length(a), length(b));init(i -> (get(i, a), get(i, b)), len)////// Returns a vector where the element at index `i` is `f(x, y)` where/// `x` is the element at index `i` in `a` and `y` is the element at index `i` in `b`.////// If either `a` or `b` becomes depleted, then no further elements are added to the resulting vector.///pubdefzipWith(f: (a, b) -> c \ ef, a: Vector[a], b: Vector[b]): Vector[c] \ ef =letlen = Int32.min(length(a), length(b));init(i -> f(get(i, a), get(i, b)), len)////// Returns a pair of vectors, the first containing all first components in `v`/// and the second containing all second components in `v`.///pubdefunzip(v: Vector[(a, b)]): (Vector[a], Vector[b]) = regionrc {letlen = length(v);letarr = Array.empty(rc, len);letbrr = Array.empty(rc, len);forEachWithIndex(i -> match (l, r) -> {Array.put(l, i, arr);Array.put(r, i, brr) },v ); (Array.toVector(arr), Array.toVector(brr)) }////// Alias for `foldLeft2`.///pubdeffold2(f: (c, a, b) -> c \ ef, c: c, a: Vector[a], b: Vector[b]): c \ ef =foldLeft2(f, c, a, b)////// Accumulates the result of applying `f` pairwise to the elements of `a` and `b`/// starting with the initial value `c` and going from left to right.///pubdeffoldLeft2(f: (c, a, b) -> c \ ef, c: c, a: Vector[a], b: Vector[b]): c \ ef =letlena = length(a);letlenb = length(b);defloop(i, acc) = {if (i>=lenaori>=lenb)accelseloop(i+1, f(acc, get(i, a), get(i, b))) };loop(0, c)////// Accumulates the result of applying `f` pairwise to the elements of `a` and `b`/// starting with the initial value `c` and going from right to left.///pubdeffoldRight2(f: (a, b, c) -> c \ ef, c: c, a: Vector[a], b: Vector[b]): c \ ef =defloop(i, j, acc) = {if (i<0orj<0)accelseloop(i-1, j-1, f(get(i, a), get(j, b), acc)) };letstarta = length(a) -1;letstartb = length(b) -1;loop(starta, startb, c)////// Collects the successful results of applying the partial function `f` to every element in `v`.///pubdeffilterMap(f: a -> Option[b] \ ef, v: Vector[a]): Vector[b] \ ef =foldRight( (x, xs) -> matchf(x) {case None => xscase Some(b) => b :: xs }, Nil,v ) |> List.toVector////// Returns the first non-None result of applying the partial function `f` to each element of `v`.////// Returns `None` if every element of `xs` is `None`.///pubdeffindMap(f: a -> Option[b] \ ef, v: Vector[a]): Option[b] \ ef =letlen = length(v);defloop(i) = {if (i>=len) Noneelseletx = f(get(i, v));matchx {case Some(a) => Some(a)case None => loop(i+1) } };loop(0)////// Returns the vector `v` as a set.///pubdeftoSet(v: Vector[a]): Set[a] withOrder[a] =foldRight(Set.insert, Set.empty(), v)////// Returns the association vector `v` as a map.////// If `v` contains multiple mappings with the same key, `toMap` does not/// make any guarantees about which mapping will be in the resulting map.///pubdeftoMap(v: Vector[(a, b)]): Map[a, b] withOrder[a] =foldRight((x, m) -> Map.insert(fst(x), snd(x), m), Map.empty(), v)////// Alias for `findIndexOfLeft`.///pubdeffindIndexOf(f: a -> Bool \ ef, v: Vector[a]): Option[Int32] \ ef =findIndexOfLeft(f, v)////// Optionally returns the position of the first element in `v` satisfying `f`.///pubdeffindIndexOfLeft(f: a -> Bool \ ef, v: Vector[a]): Option[Int32] \ ef =letlen = length(v);if (len<1) Noneelse {defloop(i) = {if (i>=len) -1elseif (f(get(i, v)))ielseloop(i+1) };leti = loop(0);if (i<0) None else Some(i) }////// Optionally returns the position of the first element in `v` satisfying `f`/// searching from right to left.///pubdeffindIndexOfRight(f: a -> Bool \ ef, v: Vector[a]): Option[Int32] \ ef =letlen = length(v);defloop(i) = {if (i<0) -1elseif (f(get(i, v)))ielseloop(i-1) };leti = loop(len-1);if (i<0) None else Some(i)////// Returns the positions of the all the elements in `v` satisfying `f`.///pubdeffindIndices(f: a -> Bool \ ef, v: Vector[a]): Vector[Int32] \ ef = regionrc {letl = MutList.empty(rc);forEachWithIndex((i, x) -> if (f(x)) { MutList.push(i, l) }, v);MutList.toVector(l) }////// Build an vector of length `len` by applying `f` to the successive indices.///pubdefinit(f: Int32 -> a \ ef, len: Int32): Vector[a] \ ef = regionrc {letarr = if (len>0) Array.empty(rc, len) else Array#{} @ rc;defloop(i) = {if (i<len) {Array.put(f(i), i, arr);loop(i+1) } };loop(0);Array.toVector(arr) }////// Returns `true` if vectors `a` and `b` have the same elements in the same order, i.e. are structurally equal.///pubdefequals(a: Vector[a], b: Vector[a]): BoolwithEq[a] =letalen = length(a);letblen = length(b);defloop(i) = {if (i>=alen)trueelseif (get(i, a) !=get(i, b))falseelseloop(i+1) };if (alen==blen)loop(0)elsefalse////// Returns an iterator over `v`///pubdefiterator(rc: Region[r], v: Vector[a]): Iterator[a, r, r] \ r =Iterator.range(rc, 0, length(v)) |> Iterator.map(i -> get(i, v))////// Apply the effectful function `f` to all the elements in the vector `v`.///pubdefforEach(f: a -> Unit \ ef, v: Vector[a]): Unit \ ef =letlen = length(v);defloop(i) = {if (i>=len)()else {f(get(i, v));loop(i+1) } };loop(0)////// Apply the effectful function `f` to all the elements in the vector `v`.///pubdefforEachWithIndex(f: (Int32, a) -> Unit \ ef, v: Vector[a]): Unit \ ef =letlen = length(v);defloop(i) = {if (i>=len)()else {f(i, get(i, v));loop(i+1) } };loop(0)////// Returns a copy of `v` with the elements starting at index `i` replaced by `sub`.///pubdefupdateSequence(i: Int32, sub: Vector[a], v: Vector[a]): Vector[a] =letend = i+length(sub);letlen = length(v);letf = ix -> if (ix>=iandix<end) get(ix-i, sub) elseget(ix, v);init(f, len)////// Returns the concatenation of the string representation/// of each element in `v` with `sep` inserted between each element.///pubdefjoin(sep: String, v: Vector[a]): StringwithToString[a] = regionrc {Vector.iterator(rc, v) |> Iterator.join(sep) }////// Returns the concatenation of the string representation/// of each element in `v` according to `f` with `sep` inserted between each element.///pubdefjoinWith(f: a -> String \ ef, sep: String, v: Vector[a]): String \ ef = regionrc {Vector.iterator(rc, v) |> Iterator.joinWith(f, sep) }////// Returns a sorted copy of vector `v`, where the 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 `v`.////// The sort implementation is a Quicksort.///pubdefsort(v: Vector[a]): Vector[a] withOrder[a] =sortWith(Order.compare, v)////// Returns a sorted copy of vector `v`, where the 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 `v`.////// The sort implementation is a Quicksort.///pubdefsortBy(f: a -> b, v: Vector[a]): Vector[a] withOrder[b] =sortWith(Order.compare`on`f, v)////// Returns a sorted copy of vector `v`, where the 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 `v`.////// The sort implementation is a Quicksort.///pubdefsortWith(cmp: (a, a) -> Comparison, v: Vector[a]): Vector[a] = regionrc {letarr = toArray(rc, v);Array.sortWith(cmp, arr);Array.toVector(arr) }////// Shuffles `v` using the Fisher–Yates shuffle.///pubdefshuffle(v: Vector[a]): Vector[a] \ Shuffle = regionrc {letarr = toArray(rc, v);Array.shuffle(arr);Array.toVector(arr) }}