/* * 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. */////// Type of optional values, and its functions.///pubmod Option {////// Type of optional values.////// The constructor `None` represents an absent value,/// whereas the constructor `Some(v)` represents the value `v`.///pubenumOption[t] withEq, Order, ToString {case Nonecase Some(t) }instanceLowerBound[Option[t]] {pubdefminValue(_: Unit): Option[t] = None }instancePartialOrder[Option[t]] withPartialOrder[t] {pubdeflessEqual(x: Option[t], y: Option[t]): Bool = match (x, y) {case (None, _) => truecase (Some(a), Some(b)) => PartialOrder.lessEqual(a, b)case_ => false } }instanceJoinLattice[Option[t]] withJoinLattice[t] {pubdefleastUpperBound(x: Option[t], y: Option[t]): Option[t] = match (x, y) {case (None, _) => ycase (_, None) => xcase (Some(a), Some(b)) => Some(JoinLattice.leastUpperBound(a, b)) } }instanceMeetLattice[Option[t]] withMeetLattice[t] {pubdefgreatestLowerBound(x: Option[t], y: Option[t]): Option[t] = match (x, y) {case (None, _) => Nonecase (_, None) => Nonecase (Some(a), Some(b)) => Some(MeetLattice.greatestLowerBound(a, b)) } }instanceHash[Option[a]] withHash[a] {pubdefhash(o: Option[a]): Int32 = matcho {case None => 1046527case Some(y) => 919*Hash.hash(y) } }instanceFunctor[Option] {pubdefmap(f: a -> b \ ef, o: Option[a]): Option[b] \ ef = Option.map(f, o) }instanceApplicative[Option] {pubdefpoint(x: a): Option[a] = Option.point(x)pubdefap(f: Option[a -> b \ ef], x: Option[a]): Option[b] \ ef = Option.ap(f, x)// Same as the default implementation using `map` and `ap` but with less indirection. redef map2(f: t1 -> t2 -> r \ ef, x1: Option[t1], x2: Option[t2]): Option[r] \ ef = Option.map2(f, x1, x2) redef map3(f: t1 -> t2 -> t3 -> r \ ef, x1: Option[t1], x2: Option[t2], x3: Option[t3]): Option[r] \ ef = Option.map3(f, x1, x2, x3) redef map4(f: t1 -> t2 -> t3 -> t4 -> r \ ef, x1: Option[t1], x2: Option[t2], x3: Option[t3], x4: Option[t4]): Option[r] \ ef = Option.map4(f, x1, x2, x3, x4) redef map5(f: t1 -> t2 -> t3 -> t4 -> t5 -> r \ ef, x1: Option[t1], x2: Option[t2], x3: Option[t3], x4: Option[t4], x5: Option[t5]): Option[r] \ ef = Option.map5(f, x1, x2, x3, x4, x5) }instanceMonad[Option] {pubdefflatMap(f: a -> Option[b] \ ef, x: Option[a]): Option[b] \ ef = Option.flatMap(f, x) }instanceMonadZero[Option] {pubdefempty(): Option[a] = None }instanceMonadZip[Option] {pubdefzipWith(f: (a, b) -> c \ ef, ma: Option[a], mb: Option[b]): Option[c] \ ef = Applicative.map2(f, ma, mb) redef zip(ma: Option[a], mb: Option[b]): Option[(a, b)] = Applicative.map2((x, y) -> (x, y), ma, mb)pubdefzipWithA(f: (a, b) -> f[c] \ ef, x: Option[a], y: Option[b]): f[Option[c]] \ efwithApplicative[f] =use Functor.{<$>};match (x, y) {case (Some(x1), Some(y1)) => Some <$> f(x1, y1)case (_, _) => Applicative.point(None) } }instanceFoldable[Option] {pubdeffoldLeft(f: (b, a) -> b \ ef, s: b, o: Option[a]): b \ ef = Option.foldLeft(f, s, o)pubdeffoldRight(f: (a, b) -> b \ ef, s: b, o: Option[a]): b \ ef = Option.foldRight(f, o, s) redef isEmpty(o: Option[a]): Bool = Option.isEmpty(o) redef forAll(f: a -> Bool \ ef, o: Option[a]): Bool \ ef = Option.forAll(f, o) redef exists(f: a -> Bool \ ef, o: Option[a]): Bool \ ef = Option.exists(f, o) }instanceUnorderedFoldable[Option] {pubdeffoldMap(f: a -> b \ ef, o: Option[a]): b \ efwithCommutativeMonoid[b] = Option.foldMap(f, o) }instanceTraversable[Option] {pubdeftraverse(f: a -> m[b] \ ef, t: Option[a]): m[Option[b]] \ efwithApplicative[m] =use Applicative.{point};use Functor.{map};matcht {case None => point(None)case Some(a) => f(a) |> map(Some) } redef sequence(t: Option[m[a]]): m[Option[a]] withApplicative[m] =use Applicative.{point};use Functor.{map};matcht {case Some(ma) => map(Some, ma)case None => point(None) } }instanceFilterable[Option] {pubdeffilterMap(f: a -> Option[b] \ ef, o: Option[a]): Option[b] \ ef = Option.flatMap(f, o) redef filter(f: a -> Bool \ ef, o: Option[a]): Option[a] \ ef = Option.filter(f, o) }instanceWitherable[Option]instanceSemiGroup[Option[a]] withSemiGroup[a] {pubdefcombine(x: Option[a], y: Option[a]): Option[a] = match (x, y) {case (a, None) => acase (None, b) => bcase (Some(x1), Some(y1)) => Some(SemiGroup.combine(x1, y1)) } }instanceCommutativeSemiGroup[Option[a]] withCommutativeSemiGroup[a]instanceMonoid[Option[a]] withMonoid[a] {pubdefempty(): Option[a] = None }instanceCommutativeMonoid[Option[a]] withCommutativeMonoid[a]instanceIterable[Option[a]] {typeElm = apubdefiterator(rc: Region[r], o: Option[a]): Iterator[a, r, r] \ r = Option.iterator(rc, o) }instanceForEach[Option[a]] {typeElm = apubdefforEach(f: a -> Unit \ ef, o: Option[a]): Unit \ ef = Option.forEach(f, o) }instanceFormattable[Option[a]] withFormattable[a] {typeAef = Formattable.Aef[a]pubdefformat(x: Option[a]): RichString \ Formattable.Aef[a] = matchx {case None => RichString.fromString("None")case Some(v) => RichString.fromString("Some(") +Formattable.format(v) +RichString.fromString(")") } }////// Returns the empty option variant `None`.///pubdefempty(): Option[a] = None////// Returns `true` iff `o` is `None`.///pubdefisEmpty(o: Option[a]): Bool = matcho {case None => truecase Some(_) => false }////// Returns `true` iff `o` is `Some`.///pubdefnonEmpty(o: Option[a]): Bool = notisEmpty(o)////// Returns `v` if `o` is `Some(v).` Otherwise returns `d`.///pubdefgetWithDefault(d: a, o: Option[a]): a = matcho {case None => dcase Some(v) => v }////// Returns `v` if `o` is `Some(v)`. Otherwise aborts with a stack trace.///pubdefgetOrAbort(o: Option[a]): a \ Abort = matcho {case None => Abort.abortWithTrace("Option.getOrAbort(): called on None")case Some(v) => v }////// Aborts with a stack trace if `o` is `None`.///pubdeforAbort(o: Option[a]): Unit \ Abort = matcho {case None => Abort.abortWithTrace("Option.orAbort(): called on None")case Some(_) => () }////// Returns `o` if it is `Some(v)`. Otherwise returns `default`.///pubdefwithDefault(default: {default = Option[a]}, o: Option[a]): Option[a] = matcho {case None => default#defaultcase Some(_) => o }////// Returns `Some(dst)` if `o` is `Some(src)`. Otherwise returns `o`.///pubdefreplace(src: {src = a}, dst: {dst = a}, o: Option[a]): Option[a] withEq[a] = matcho {case None => ocase Some(v) => Some(if (v==src#src) dst#dst elsev) }////// Returns `true` if `o` is `Some(v)` and the predicate `f(v)` evaluates to `true`. Otherwise returns `false`.///pubdefexists(f: a -> Bool \ ef, o: Option[a]): Bool \ ef = matcho {case None => falsecase Some(v) => f(v) }////// Returns `true` if `o` is `Some(v)` and the predicate `f(v)` evaluates to `true` or if `o` is `None`.////// Otherwise returns `false`.///pubdefforAll(f: a -> Bool \ ef, o: Option[a]): Bool \ ef = matcho {case None => truecase Some(v) => f(v) }////// Returns `o` if `o` is `Some(v)` and the predicate `f(v)` is true. Otherwise returns `None`.///pubdeffilter(f: a -> Bool \ ef, o: Option[a]): Option[a] \ ef = matcho {case None => Nonecase Some(v) => if (f(v)) oelse None }////// Returns `Some(f(v))` if `o` is `Some(v)`. Otherwise returns `None`.///pubdefmap(f: a -> b \ ef, o: Option[a]): Option[b] \ ef = matcho {case None => Nonecase Some(v) => Some(f(v)) }////// Returns `Some(x)`.///pubdefpoint(x: a): Option[a] = Some(x)////// If both arguments are `Some`, return a `Some` containing the result of applying the function inside/// `f` to the value inside `x`. Otherwise return `None`.///pubdefap(f: Option[a -> b \ ef], x: Option[a]): Option[b] \ ef =matchf {case None => Nonecase Some(g) =>matchx {case None => Nonecase Some(y) => Some(g(y)) } }////// Returns `f(v)` if `o` is `Some(v)`. Otherwise returns `None`.///pubdefflatMap(f: a -> Option[b] \ ef, o: Option[a]): Option[b] \ ef = matcho {case None => Nonecase Some(v) => f(v) }////// Returns `1` if `o` is `Some(v)` and the predicate `f(v)` evaluates to `true`. Otherwise returns `0`.///pubdefcount(f: a -> Bool \ ef, o: Option[a]): Int32 \ ef = matcho {case None => 0case Some(v) => if (f(v)) 1else0 }////// Returns `v` if `o` is `Some(v)` else `0`.///pubdefsum(o: Option[Int32]): Int32 =Foldable.sum(o)////// Returns `f(v)` if `o` is `Some(v)` else `0`.///pubdefsumWith(f: a -> Int32 \ ef, o: Option[a]): Int32 \ ef =Foldable.sumWith(f, o)////// Returns `o` if `o` is `Some(v)` and the predicate `f(v)` evaluates to `true`. Otherwise returns `None`.////// The function `f` must be pure.///pubdeffind(f: a -> Bool, o: Option[a]): Option[a] = matcho {case None => Nonecase Some(v) => if (f(v)) oelse None }////// Returns `v` if `o` is `Some(v)`. Otherwise returns `None`.///pubdefflatten(o: Option[Option[a]]): Option[a] = matcho {case None => Nonecase Some(v) => v }////// Returns the result of applying `combine` to all the elements in `o`, using `empty` as the initial value.///pubdeffold(o: Option[a]): awithMonoid[a] = Foldable.fold(o)////// Returns `f(z, v)` if `o` is `Some(v)`. Otherwise returns `z`.///pubdeffoldLeft(f: (b, a) -> b \ ef, z: b, o: Option[a]): b \ ef = matcho {case None => zcase Some(v) => f(z, v) }////// Returns `f(v, z)` if `o` is `Some(v)`. Otherwise returns `z`.///pubdeffoldRight(f: (a, b) -> b \ ef, o: Option[a], z: b): b \ ef = matcho {case None => zcase Some(v) => f(v, z) }////// Returns the result of mapping each element and combining the results.///pubdeffoldMap(f: a -> b \ ef, o: Option[a]): b \ efwithMonoid[b] =foldLeft((acc, x) -> Monoid.combine(acc, f(x)), Monoid.empty(), o)////// Returns `Some(v1 :: v2 :: ... :: vn)` if each of `xs_i` is `Some(v_i)`. Otherwise returns `None`.///pubdefsequence(l: List[Option[a]]): Option[List[a]] =defloop(ll, k) = matchll {case Nil => k(Nil)case None :: _ => Nonecase Some(x) :: xs => loop(xs, ks -> k(x :: ks)) };loop(l, ks -> Some(ks))////// Returns `Some(v1 :: v2 :: ... v :: vn)` if each of `f(l_i)` is `Some(v_i)`. Otherwise returns `None`.///pubdeftraverse(f: a -> Option[b] \ ef, l: List[a]): Option[List[b]] \ ef =defloop(ll, k) = matchll {case Nil => k(Nil)casex :: xs =>matchf(x) {case None => Nonecase Some(y) => loop(xs, ys -> k(y :: ys)) } };loop(l, ks -> Some(ks))////// Returns `Some()` if each of `f(l_i)` is `Some(_)`. Otherwise returns `None`.////// 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 -> Option[b] \ ef, l: List[a]): Option[Unit] \ ef = matchl {case Nil => Some()casex :: xs =>matchf(x) {case None => Nonecase Some(_) => traverseX(f, xs) } }////// 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 `None` value) the traversal/// of `l` is short-circuited and `None` is returned.////// If `f` is successfully applied to all the elements in `l` the result is of the form:/// `Some(f(...f(f(s, x1), x2)..., xn))`.///pubdeffoldLeftM(f: (b, a) -> Option[b] \ ef, s: b, l: List[a]): Option[b] \ ef = matchl {case Nil => Some(s)casex :: xs =>matchf(s, x) {case Some(s1) => foldLeftM(f, s1, xs)case None => None } }////// 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 `None` value) the traversal/// of `l` is short-circuited and `None` is returned.////// If `f` is successfully applied to all elements in `l` the result is of the form:/// `Some(f(x1, ...f(xn-1, f(xn, s))...))`.///pubdeffoldRightM(f: (a, b) -> Option[b] \ ef, s: b, l: List[a]): Option[b] \ ef =defloop(ll, k) = matchll {case Nil => k(s)casex :: xs =>loop(xs,s1 -> matchf(x, s1) {case Some(s2) => k(s2)case None => None } ) };loop(l, s1 -> checked_ecast(Some(s1)))////// Returns a one-element list of the value `v` if `o` is `Some(v)`. Otherwise returns the empty list.///pubdeftoList(o: Option[a]): List[a] = matcho {case None => Nilcase Some(v) => v :: Nil }////// Returns a one-element set of the value `v` if `o` is `Some(v)`. Otherwise returns the empty set.///pubdeftoSet(o: Option[a]): Set[a] withOrder[a] = matcho {case None => Set.empty()case Some(v) => Set.singleton(v) }////// Returns a singleton map with the mapping `k -> v` if `o` is `Some((k, v))`. Otherwise returns the empty map.///pubdeftoMap(o: Option[(k, v)]): Map[k, v] withOrder[k] = matcho {case None => Map.empty()case Some((k, v)) => Map.singleton(k, v) }////// Returns a map with elements of `s` as keys and `f` applied as values.///pubdeftoMapWith(f: a -> b, s: Option[a]): Map[a, b] withOrder[a] =Option.foldRight((x, acc) -> Map.insert(x, f(x), acc), s, Map.empty())////// Returns the Option value `Ok(v)` if `o` is `Some(v)`. Otherwise returns `Err(e)`.///pubdeftoOk(e: e, o: Option[t]): Result[e, t] = matcho {case None => Err(e)case Some(a) => Ok(a) }////// Returns the Option value `Err(e)` if `o` is `Some(e)`. Otherwise returns `Ok(d)`.///pubdeftoErr(d: t, o: Option[e]): Result[e, t] = matcho {case None => Ok(d)case Some(e) => Err(e) }////// Returns the Validation value `Success(v)` if `o` is `Some(v)`. Otherwise lifts `e` into Validation's `Failure`.///pubdeftoSuccess(e: e, o: Option[t]): Validation[e, t] = matcho {case None => Validation.Failure(Nec.singleton(e))case Some(a) => Validation.Success(a) }////// Returns `e` into Validation's `Failure` if `o` is `Some(e)`. Otherwise returns `Success(d)`.///pubdeftoFailure(d: t, o: Option[e]): Validation[e, t] = matcho {case None => Validation.Success(d)case Some(e) => Validation.Failure(Nec.singleton(e)) }////// Returns `Some((v1, v2))` if `o1` is `Some(v1)` and `o2` is `Some(v2)`. Otherwise returns `None`.///pubdefzip(o1: Option[a], o2: Option[b]): Option[(a, b)] = match (o1, o2) {case (None, _) => Nonecase (_, None) => Nonecase (Some(v1), Some(v2)) => Some((v1, v2)) }////// Returns `(Some(v1), Some(v2))` if `o` is `Some((v1, v2))`. Otherwise returns `(None, None)`.///pubdefunzip(o: Option[(a, b)]): (Option[a], Option[b]) = matcho {case None => (None, None)case Some((v1, v2)) => (Some(v1), Some(v2)) }////// Applies `f` to `v` if `o` is `Some(v)`. Otherwise does nothing.///pubdefforEach(f: a -> Unit \ ef, o: Option[a]): Unit \ ef = matcho {case None => ()case Some(v) => f(v) }////// Applies the binary function `f` to the values in `o1` and `o2`.////// Returns `None` if either `o1` or `o2` are `None`.///pubdefmap2(f: (t1, t2) -> u \ ef, o1: Option[t1], o2: Option[t2]): Option[u] \ ef =ap(map(f, o1), o2)////// Applies the ternary function `f` to the values in `o1`, `o2` and `o3`.////// Returns `None` if any of `o1`, `o2` and `o3` are `None`.///pubdefmap3(f: (t1, t2, t3) -> u \ ef, o1: Option[t1], o2: Option[t2], o3: Option[t3]): Option[u] \ ef =ap(map2(f, o1, o2), o3)////// Applies the 4-ary function `f` to the values in `o1`, `o2`, `o3` and `o4`.////// Returns `None` if any of `o1`, `o2`, `o3` and `o4` are `None`.///pubdefmap4(f: (t1, t2, t3, t4) -> u \ ef, o1: Option[t1], o2: Option[t2], o3: Option[t3], o4: Option[t4]): Option[u] \ ef =ap(map3(f, o1, o2, o3), o4)////// Applies the 5-ary function `f` to the values in `o1`, `o2`, ... `o5`.////// Returns `None` if any of `o1`, `o2`, ... `o5` are `None`.///pubdefmap5(f: (t1, t2, t3, t4, t5) -> u \ ef, o1: Option[t1], o2: Option[t2], o3: Option[t3], o4: Option[t4], o5: Option[t5]): Option[u] \ ef =ap(map4(f, o1, o2, o3, o4), o5)////// Applies the 6-ary function `f` to the values in `o1`, `o2`, ... `o6`.////// Returns `None` if any of `o1`, `o2`, ... `o6` are `None`.///pubdefmap6(f: (t1, t2, t3, t4, t5, t6) -> u \ ef, o1: Option[t1], o2: Option[t2], o3: Option[t3], o4: Option[t4], o5: Option[t5], o6: Option[t6]): Option[u] \ ef =ap(map5(f, o1, o2, o3, o4, o5), o6)////// Applies the 7-ary function `f` to the values in `o1`, `o2`, ... `o7`.////// Returns `None` if any of `o1`, `o2`, ... `o7` are `None`.///pubdefmap7(f: (t1, t2, t3, t4, t5, t6, t7) -> u \ ef, o1: Option[t1], o2: Option[t2], o3: Option[t3], o4: Option[t4], o5: Option[t5], o6: Option[t6], o7: Option[t7]): Option[u] \ ef =ap(map6(f, o1, o2, o3, o4, o5, o6), o7)////// Applies the 8-ary function `f` to the values in `o1`, `o2`, ... `o8`.////// Returns `None` if any of `o1`, `o2`, ... `o8` are `None`.///pubdefmap8(f: (t1, t2, t3, t4, t5, t6, t7, t8) -> u \ ef, o1: Option[t1], o2: Option[t2], o3: Option[t3], o4: Option[t4], o5: Option[t5], o6: Option[t6], o7: Option[t7], o8: Option[t8]): Option[u] \ ef =ap(map7(f, o1, o2, o3, o4, o5, o6, o7), o8)////// Applies the 9-ary function `f` to the values in `o1`, `o2`, ... `o9`.////// Returns `None` if any of `o1`, `o2`, ... `o9` are `None`.///pubdefmap9(f: (t1, t2, t3, t4, t5, t6, t7, t8, t9) -> u \ ef, o1: Option[t1], o2: Option[t2], o3: Option[t3], o4: Option[t4], o5: Option[t5], o6: Option[t6], o7: Option[t7], o8: Option[t8], o9: Option[t9]): Option[u] \ ef =ap(map8(f, o1, o2, o3, o4, o5, o6, o7, o8), o9)////// Applies the 10-ary function `f` to the values in `o1`, `o2`, ... `o10`.////// Returns `None` if any of `o1`, `o2`, ... `o10` are `None`.///pubdefmap10(f: (t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) -> u \ ef, o1: Option[t1], o2: Option[t2], o3: Option[t3], o4: Option[t4], o5: Option[t5], o6: Option[t6], o7: Option[t7], o8: Option[t8], o9: Option[t9], o10: Option[t10]): Option[u] \ ef =ap(map9(f, o1, o2, o3, o4, o5, o6, o7, o8, o9), o10)////// Returns an iterator over `o` with 1 element or an empty iterator if `o` is `None`.///pubdefiterator(rc: Region[r], o: Option[a]): Iterator[a, r, r] \ r = matcho {case None => Iterator.empty(rc)case Some(x) => Iterator.singleton(rc, x) }}