/* * Copyright 2019 Liam Palmer, Magnus Madsen * * Use of this source code is governed by the Apache 2.0 license * that can be found in the LICENSE.md file. */pubmod Result {////// The Result type.////// A result represents a successful value or an error value./// The constructor `Ok(v)` represents the successful value `v`,/// whereas the constructor `Err(v)` represents the error value `v`.///pubenumResult[e, t] withEq, Order, ToString {case Ok(t)case Err(e) }instanceHash[Result[e, t]] withHash[e], Hash[t] {pubdefhash(r: Result[e, t]): Int32 = matchr {case Ok(v) => 5381+113*Hash.hash(v)case Err(v) => 5351+97*Hash.hash(v) } }instanceFunctor[Result[e]] {pubdefmap(f: a -> b \ ef, x: Result[e, a]): Result[e, b] \ ef = Result.map(f, x) }instanceApplicative[Result[e]] {pubdefpoint(a: a): Result[e, a] = Ok(a)pubdefap(f: Result[e, a -> b \ ef], x: Result[e, a]): Result[e, b] \ ef = Result.ap(f, x) }instanceMonad[Result[e]] {pubdefflatMap(f: a -> Result[e, b] \ ef, x: Result[e, a]): Result[e, b] \ ef = Result.flatMap(f, x) }instanceFormattable[Result[e, t]] withFormattable[e], Formattable[t] {typeAef = Formattable.Aef[e] + Formattable.Aef[t]pubdefformat(x: Result[e, t]): RichString \ (Formattable.Aef[e] + Formattable.Aef[t]) = matchx {case Ok(v) => RichString.fromString("Ok(") +Formattable.format(v) +RichString.fromString(")")case Err(e) => RichString.fromString("Err(") +Formattable.format(e) +RichString.fromString(")") } }////// Returns `true` iff `r` is `Ok(v)`.///pubdefisOk(r: Result[e, t]): Bool = matchr {case Ok(_) => truecase Err(_) => false }////// Returns `true` iff `r` is `Err(w)`.///pubdefisErr(r: Result[e, t]): Bool = matchr {case Ok(_) => falsecase Err(_) => true }////// Returns `v` if `r` is `Ok(v)`. Otherwise returns `d`.///pubdefgetWithDefault(d: t, r: Result[e, t]): t = matchr {case Ok(v) => vcase Err(_) => d }////// Returns `v` if `r` is `Ok(v)`. Otherwise aborts with a stack trace.///pubdefgetOrAbort(r: Result[e, t]): t \ Abort = matchr {case Ok(v) => vcase Err(_) => Abort.abortWithTrace("Result.getOrAbort(): called on Err") }////// Aborts with a stack trace if `r` is `Err`.///pubdeforAbort(r: Result[e, t]): Unit \ Abort = matchr {case Ok(_) => ()case Err(_) => Abort.abortWithTrace("Result.orAbort(): called on Err") }////// Returns `Ok(v)` if `r` is `Ok(v)`. Otherwise returns `default`.///pubdefwithDefault(default: {default = Result[e2, t]}, r: Result[e1, t]): Result[e2, t] = matchr {case Ok(v) => Ok(v)case Err(_) => default#default }////// Returns `Ok(dst)` if `r` is `Ok(src)`. Otherwise returns `r`.///pubdefreplace(src: {src = t}, dst: {dst = t}, r: Result[e, t]): Result[e, t] withEq[t] = matchr {case Ok(v) => Ok(if (v==src#src) dst#dst elsev)case Err(_) => r }////// Returns `true` if `r` is `Ok(v)` and the predicate `f(v)` evaluates to `true`. Otherwise returns `false`.///pubdefexists(f: t -> Bool \ ef, r: Result[e, t]): Bool \ ef = matchr {case Ok(t) => f(t)case Err(_) => false }////// Returns `true` if `r` is `Ok(v)` and the predicate `f(v)` evaluates to `true` or if `r` is `Err(w)`./// Otherwise returns `false`.///pubdefforAll(f: t -> Bool \ ef, r: Result[e, t]): Bool \ ef = matchr {case Ok(t) => f(t)case Err(_) => true }////// Returns `Ok(f(v))` if `r` is `Ok(v)`. Returns `Err(w)` if `r` is `Err(w)`.///pubdefmap(f: t1 -> t2 \ ef, r: Result[e, t1]): Result[e, t2] \ ef = matchr {case Ok(v) => Ok(f(v))case Err(w) => Err(w) }////// Returns `Err(f(e))` if `r` is `Err(e)`. Returns `Ok(v)` if `r` is `Ok(v)`.///pubdefmapErr(f: e1 -> e2 \ ef, r: Result[e1, t]): Result[e2, t] \ ef = matchr {case Ok(v) => Ok(v)case Err(w) => Err(f(w)) }////// Returns `f(v)` if `r` is `Ok(v)`. Returns `Err(w)` if `r` is `Err(w)`.///pubdefflatMap(f: t1 -> Result[e, t2] \ ef, r: Result[e, t1]): Result[e, t2] \ ef = matchr {case Ok(v) => f(v)case Err(w) => Err(w) }////// Returns `v` if `r` is `Ok(v)`. Returns `Err(w)` if `r` is `Err(w)`.///pubdefflatten(r: Result[e, Result[e, t]]): Result[e, t] = matchr {case Ok(v) => vcase Err(w) => Err(w) }////// Returns `1` if `r` is `Ok(v)` and the predicate `f(v)` evaluates to `true`. Otherwise returns `0`.///pubdefcount(f: t -> Bool \ ef, r: Result[e, t]): Int32 \ ef = matchr {case Ok(v) => if (f(v)) 1else0case Err(_) => 0 }////// Returns `v` if `r` is `Ok(v)` else `0`.///pubdefsum(r: Result[e, Int32]): Int32 =foldLeft((+), 0, r)////// Returns `f(v)` if `r` is `Ok(v)` else `0`.///pubdefsumWith(f: t -> Int32 \ ef, r: Result[e, t]): Int32 \ ef =foldLeft((acc, x) -> acc+f(x), 0, r)////// Returns `Some(v)` if `r` is `Ok(v)` and the predicate `f(v)` evaluates to `true`. Otherwise returns `None`.////// The function `f` must be pure.///pubdeffind(f: t -> Bool, r: Result[e, t]): Option[t] = matchr {case Ok(v) => if (f(v)) Some(v) else Nonecase Err(_) => None }////// Returns `f(z, v)` if `r` is `Ok(v)`. Otherwise returns `z`.///pubdeffoldLeft(f: (a, t) -> a \ ef, z: a, r: Result[e, t]): a \ ef = matchr {case Ok(v) => f(z, v)case Err(_) => z }////// Returns `f(v, z)` if `r` is `Ok(v)`. Otherwise returns `z`.///pubdeffoldRight(f: (t, a) -> a \ ef, z: a, r: Result[e, t]): a \ ef = matchr {case Ok(v) => f(v, z)case Err(_) => z }////// Returns `Ok(v1 :: v2 :: ... :: vn)` if each of `l_i` is `Ok(v_i)`./// Otherwise returns the first `Err` encountered.///pubdefsequence(l: List[Result[e, a]]): Result[e, List[a]] =defloop(ll, k) = matchll {case Nil => k(Nil)case Err(e) :: _ => Err(e)case Ok(x) :: xs => loop(xs, ks -> k(x :: ks)) };loop(l, ks -> Ok(ks))////// Returns `Ok(v1 :: v2 :: ... v :: vn)` if each of `f(l_i)` is `Ok(v_i)`./// Otherwise returns the first `Err` encountered.///pubdeftraverse(f: a -> Result[e, b] \ ef, l: List[a]): Result[e, List[b]] \ ef =defloop(ll, k) = matchll {case Nil => k(Nil)casex :: xs => matchf(x) {case Ok(y) => loop(xs, ks -> k(y :: ks))case Err(e) => Err(e) } };loop(l, ks -> Ok(ks))////// Returns `Ok()` if each of `f(l_i)` is `Ok(_)`. Otherwise returns the first `Err`.////// This function is the "forgetful" version of `traverse`, use it when you want the effect/// of applying `f` to each element but do not care about collecting the results.///pubdeftraverseX(f: a -> Result[e, b] \ ef, l: List[a]): Result[e, Unit] \ ef = matchl {case Nil => Ok()casex :: xs => matchf(x) {case Ok(_) => traverseX(f, xs)case Err(e) => Err(e) } }////// Returns the result of applying `f` to a start value `s` and the elements in `l`/// going from left to right.////// If at any step applying `f` fails (i.e. it produces a `Err(e)` value) the traversal/// of `l` is short-circuited and `Err(e)` is returned.////// If `f` is successfully applied to all elements in `l` the result is of the form:/// `Ok(f(...f(f(s, x1), x2)..., xn))`.///pubdeffoldLeftM(f: (b, a) -> Result[e, b] \ ef, s: b, l: List[a]): Result[e, b] \ ef = matchl {case Nil => Ok(s)casex :: xs => matchf(s, x) {case Ok(s1) => foldLeftM(f, s1, xs)case Err(e) => Err(e) } }////// Returns the result of applying `f` to a start value `s` and the elements in `l`/// going from right to left.////// If at any step applying `f` fails (i.e. it produces a `Err(e)` value) the traversal/// of `l` is short-circuited and `Err(e)` is returned.////// If `f` is successfully applied to all elements in `l` the result is of the form:/// `Ok(f(x1, ...f(xn-1, f(xn, s))...))`.///pubdeffoldRightM(f: (a, b) -> Result[e, b] \ ef, s: b, l: List[a]): Result[e, b] \ ef =defloop(ll, k) = matchll {case Nil => k(s)casex :: xs => loop(xs,s1 -> matchf(x, s1) {case Ok(s2) => k(s2)case Err(e) => Err(e) } ) };loop(l, s1 -> checked_ecast(Ok(s1)))////// Returns a one-element list of the value `v` if `r` is `Ok(v)`. Otherwise returns the empty list.///pubdeftoList(r: Result[e, t]): List[t] = matchr {case Ok(v) => v :: Nilcase Err(_) => Nil }////// Returns a one-element set of the value `v` if `r` is `Ok(v)`. Otherwise returns the empty set.///pubdeftoSet(r: Result[e, t]): Set[t] withOrder[t] = matchr {case Ok(v) => Set.singleton(v)case Err(_) => Set.empty() }////// Returns a singleton map with the mapping `k -> v` if `r` is `Ok((k, v))`. Otherwise returns the empty map.///pubdeftoMap(r: Result[e, (k, v)]): Map[k, v] withOrder[k] = matchr {case Ok((k, v)) => Map.singleton(k, v)case Err(_) => Map.empty() }////// Returns a map with elements of `s` as keys and `f` applied as values.///pubdeftoMapWith(f: a -> b, s: Result[a, a]): Map[a, b] withOrder[a] =Result.foldRight((x, acc) -> Map.insert(x, f(x), acc), Map.empty(), s)////// Returns `Some(v)` if `r` is `Ok(v)`. Otherwise returns `None`.///pubdeftoOption(r: Result[e, t]): Option[t] = matchr {case Ok(v) => Some(v)case Err(_) => None }////// Returns a `Success(v)` if `r` is `Ok(v)`. Otherwise returns a/// `Failure(Nec.singleton(t))` if `r` is `Err(t)`.///pubdeftoValidation(r: Result[e, t]): Validation[e, t] = matchr {case Ok(v) => Validation.Success(v)case Err(t) => Validation.Failure(Nec.singleton(t)) }////// Applies `f` to `v` if `r` is `Ok(v)`. Otherwise does nothing.///pubdefforEach(f: t -> Unit \ ef, r: Result[e, t]): Unit \ ef = matchr {case Ok(v) => f(v)case Err(_) => () }////// Applies the function in `r1` to the value in `r2`.///pubdefap(r1: Result[e, t -> u \ ef], r2: Result[e, t]): Result[e, u] \ ef = matchr1 {case Err(e) => Err(e)case Ok(f) => matchr2 {case Ok(a) => Ok(f(a))case Err(e) => Err(e) } }////// Applies the binary function `f` to the values in `r1` and `r2`.////// Returns the first `Err(e)` value if either of `r1` and `r2` are `Err(e)`.///pubdefmap2(f: (t1, t2) -> u \ ef, r1: Result[e, t1], r2: Result[e, t2]): Result[e, u] \ ef =ap(map(f, r1), r2)////// Applies the ternary function `f` to the values in `r1`, `r2` and `r3`.////// Returns the first `Err(e)` value if any of `r1`, `r2` and `r3` are `Err(e)`.///pubdefmap3(f: (t1, t2, t3) -> u \ ef, r1: Result[e, t1], r2: Result[e, t2], r3: Result[e, t3]): Result[e, u] \ ef =ap(map2(f, r1, r2), r3)////// Applies the 4-ary function `f` to the values in `r1`, `r2`, `r3` and `r4`.////// Returns the first `Err(e)` value if any of `r1`, `r2`, `r3` and `r4` are `Err(e)`.///pubdefmap4(f: (t1, t2, t3, t4) -> u \ ef, r1: Result[e, t1], r2: Result[e, t2], r3: Result[e, t3], r4: Result[e, t4]): Result[e, u] \ ef =ap(map3(f, r1, r2, r3), r4)////// Applies the 5-ary function `f` to the values in `r1`, `r2`, ... `r5`.////// Returns the first `Err(e)` value if any of `r1`, `r2`, ... `r5` are `Err(e)`.///pubdefmap5(f: (t1, t2, t3, t4, t5) -> u \ ef, r1: Result[e, t1], r2: Result[e, t2], r3: Result[e, t3], r4: Result[e, t4], r5: Result[e, t5]): Result[e, u] \ ef =ap(map4(f, r1, r2, r3, r4), r5)////// Applies the 6-ary function `f` to the values in `r1`, `r2`, ... `r6`.////// Returns the first `Err(e)` value if any of `r1`, `r2`, ... `r6` are `Err(e)`.///pubdefmap6(f: (t1, t2, t3, t4, t5, t6) -> u \ ef, r1: Result[e, t1], r2: Result[e, t2], r3: Result[e, t3], r4: Result[e, t4], r5: Result[e, t5], r6: Result[e, t6]): Result[e, u] \ ef =ap(map5(f, r1, r2, r3, r4, r5), r6)////// Applies the 7-ary function `f` to the values in `r1`, `r2`, ... `r7`.////// Returns the first `Err(e)` value if any of `r1`, `r2`, ... `r7` are `Err(e)`.///pubdefmap7(f: (t1, t2, t3, t4, t5, t6, t7) -> u \ ef, r1: Result[e, t1], r2: Result[e, t2], r3: Result[e, t3], r4: Result[e, t4], r5: Result[e, t5], r6: Result[e, t6], r7: Result[e, t7]): Result[e, u] \ ef =ap(map6(f, r1, r2, r3, r4, r5, r6), r7)////// Applies the 8-ary function `f` to the values in `r1`, `r2`, ... `r8`.////// Returns the first `Err(e)` value if any of `r1`, `r2`, ... `r8` are `Err(e)`.///pubdefmap8(f: (t1, t2, t3, t4, t5, t6, t7, t8) -> u \ ef, r1: Result[e, t1], r2: Result[e, t2], r3: Result[e, t3], r4: Result[e, t4], r5: Result[e, t5], r6: Result[e, t6], r7: Result[e, t7], r8: Result[e, t8]): Result[e, u] \ ef =ap(map7(f, r1, r2, r3, r4, r5, r6, r7), r8)////// Applies the 9-ary function `f` to the values in `r1`, `r2`, ... `r9`.////// Returns the first `Err(e)` value if any of `r1`, `r2`, ... `r9` are `Err(e)`.///pubdefmap9(f: (t1, t2, t3, t4, t5, t6, t7, t8, t9) -> u \ ef, r1: Result[e, t1], r2: Result[e, t2], r3: Result[e, t3], r4: Result[e, t4], r5: Result[e, t5], r6: Result[e, t6], r7: Result[e, t7], r8: Result[e, t8], r9: Result[e, t9]): Result[e, u] \ ef =ap(map8(f, r1, r2, r3, r4, r5, r6, r7, r8), r9)////// Applies the 10-ary function `f` to the values in `r1`, `r2`, ... `r10`.////// Returns the first `Err(e)` value if any of `r1`, `r2`, ... `r10` are `Err(e)`.///pubdefmap10(f: (t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) -> u \ ef, r1: Result[e, t1], r2: Result[e, t2], r3: Result[e, t3], r4: Result[e, t4], r5: Result[e, t5], r6: Result[e, t6], r7: Result[e, t7], r8: Result[e, t8], r9: Result[e, t9], r10: Result[e, t10]): Result[e, u] \ ef =ap(map9(f, r1, r2, r3, r4, r5, r6, r7, r8, r9), r10)////// Returns an iterator over `r` with 1 element or an empty iterator if `r` is `Err`.///pubdefiterator(rc: Region[r], r: Result[e, t]): Iterator[t, r, r] \ r = matchr {case Err(_) => Iterator.empty(rc)case Ok(x) => Iterator.singleton(rc, x) }}