/*---------------------------------------------------------------------------
  Copyright 2012-2024, Microsoft Research, Daan Leijen.

  This is free software; you can redistribute it and/or modify it under the
  terms of the Apache License, Version 2.0. A copy of the License can be
  found in the LICENSE file at the root of this distribution.
---------------------------------------------------------------------------*/

// Standard `:maybe2` functions which, unlike `:maybe`, can contain 2 values to avoid boxing allocations.
module std/core/maybe2std/core/maybe2

import std/core/typesstd/core/types
import std/core/hndstd/core/hnd
import std/core/exnstd/core/exn

// Match a `:maybe2` value and either return a default value on `Nothing2` or apply a function to the value on `Just2`
pub fun maybe2std/core/maybe2/maybe2: forall<a,b,c,e> (m : maybe2<a,b>, onNothing : c, onJust : (a, b) -> e c) -> e c( mm: maybe2<$120,$121> : maybe2std/core/types/maybe2: (V, V) -> V<aa: V,bb: V>, onNothingonNothing: $122: cc: V, onJustonJust: ($120, $121) -> $123 $122: (aa: V,bb: V) -> ee: E cc: V )result: -> 163 162 : ee: E cc: V
  match mm: maybe2<$120,$121>
    Nothing2std/core/types/Nothing2: forall<a,b> maybe2<a,b>   -> onNothingonNothing: $122
    Just2std/core/types/Just2: forall<a,b> (fst : a, snd : b) -> maybe2<a,b>(xx: $120,yy: $121) -> onJustonJust: ($120, $121) -> $123 $122(xx: $120,yy: $121)

// Convert a `:maybe2<a,b>` value to `:(a,b)`, using the `nothing` parameter for `Nothing2`.
pub fun defaultstd/core/maybe2/default: forall<a,b> (m : maybe2<a,b>, nothing : (a, b)) -> (a, b)( mm: maybe2<$176,$177> : maybe2std/core/types/maybe2: (V, V) -> V<aa: V,bb: V>, nothingnothing: ($176, $177) : (std/core/types/tuple2: (V, V) -> Vaa: V,bb: V) )result: -> total (215, 216) : (std/core/types/tuple2: (V, V) -> Vaa: V,bb: V)
  match mm: maybe2<$176,$177>
    Nothing2std/core/types/Nothing2: forall<a,b> maybe2<a,b>   -> nothingnothing: ($176, $177)
    Just2std/core/types/Just2: forall<a,b> (fst : a, snd : b) -> maybe2<a,b>(xx: $176,yy: $177) -> (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)xx: $176,yy: $177)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)

// Get the value of the `Just` constructor or raise an exception
pub fun unjuststd/core/maybe2/unjust: forall<a,b> (m : maybe2<a,b>, @implicit/kk-file-line : string) -> exn (a, b)( mm: maybe2<$224,$225> : maybe2std/core/types/maybe2: (V, V) -> V<aa: V,bb: V>, @implicit/kk-file-line?kk-file-line: string: stringstd/core/types/string: V)result: -> exn (279, 280) : exnstd/core/exn/exn: (E, V) -> V (std/core/types/tuple2: (V, V) -> Vaa: V,bb: V)
  match mm: maybe2<$224,$225>
    Just2std/core/types/Just2: forall<a,b> (fst : a, snd : b) -> maybe2<a,b>(xx: $224,yy: $225) -> (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)xx: $224,yy: $225)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)
    Nothing2std/core/types/Nothing2: forall<a,b> maybe2<a,b>   -> throwstd/core/exn/throw: (message : string, info : ? exception-info) -> exn ($224, $225)("unexpected Nothing2 in "literal: string
count= 23
++std/core/types/(++): (x : string, y : string) -> exn string @implicit/kk-file-line?kk-file-line: string
) // Get the value of the `Just` constructor or raise an exception pub fun expectstd/core/maybe2/expect: forall<a,b> (m : maybe2<a,b>, error-msg : string) -> exn (a, b)( mm: maybe2<$288,$289> : maybe2std/core/types/maybe2: (V, V) -> V<aa: V,bb: V>, error-msgerror-msg: string: stringstd/core/types/string: V)result: -> exn (336, 337) : exnstd/core/exn/exn: (E, V) -> V (std/core/types/tuple2: (V, V) -> Vaa: V,bb: V) match mm: maybe2<$288,$289> Just2std/core/types/Just2: forall<a,b> (fst : a, snd : b) -> maybe2<a,b>(xx: $288,yy: $289) -> (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)xx: $288,yy: $289)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) Nothing2std/core/types/Nothing2: forall<a,b> maybe2<a,b> -> throwstd/core/exn/throw: (message : string, info : ? exception-info) -> exn ($288, $289)(error-msgerror-msg: string) pub fun mapstd/core/maybe2/map: forall<a,b,c,d,e> (m : maybe2<a,b>, f : (a, b) -> e (c, d)) -> e maybe2<c,d>( mm: maybe2<$345,$346> : maybe2std/core/types/maybe2: (V, V) -> V<aa: V,bb: V>, ff: ($345, $346) -> $349 ($347, $348) : (aa: V,bb: V) -> ee: E (std/core/types/tuple2: (V, V) -> Vcc: V,dd: V) )result: -> 416 maybe2<414,415> : ee: E maybe2std/core/types/maybe2: (V, V) -> V<cc: V,dd: V> match mm: maybe2<$345,$346> Nothing2std/core/types/Nothing2: forall<a,b> maybe2<a,b> -> Nothing2std/core/types/Nothing2: forall<a,b> maybe2<a,b> Just2std/core/types/Just2: forall<a,b> (fst : a, snd : b) -> maybe2<a,b>(xx: $345,yy: $346) -> match ff: ($345, $346) -> $349 ($347, $348)(xx: $345,yy: $346) (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)fxfx: $347,fyfy: $348)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) -> Just2std/core/types/Just2: forall<a,b> (fst : a, snd : b) -> maybe2<a,b>(fxfx: $347,fyfy: $348) pub fun (||)std/core/maybe2/(||): forall<a,b> (m1 : maybe2<a,b>, m2 : maybe2<a,b>) -> maybe2<a,b>( m1m1: maybe2<$432,$433> : maybe2std/core/types/maybe2: (V, V) -> V<aa: V,bb: V>, m2m2: maybe2<$432,$433>: maybe2std/core/types/maybe2: (V, V) -> V<aa: V,bb: V> )result: -> total maybe2<456,457> : maybe2std/core/types/maybe2: (V, V) -> V<aa: V,bb: V> match m1m1: maybe2<$432,$433> Nothing2std/core/types/Nothing2: forall<a,b> maybe2<a,b> -> m2m2: maybe2<$432,$433> _ -> m1m1: maybe2<$432,$433> // Equality on `:maybe` pub fun (==)std/core/maybe2/(==): forall<a,b> (mb1 : maybe2<a,b>, mb2 : maybe2<a,b>, @implicit/fst/(==) : (a, a) -> bool, @implicit/snd/(==) : (b, b) -> bool) -> bool( mb1mb1: maybe2<$465,$466> : maybe2std/core/types/maybe2: (V, V) -> V<aa: V,bb: V>, mb2mb2: maybe2<$465,$466> : maybe2std/core/types/maybe2: (V, V) -> V<aa: V,bb: V>, (@implicit/fst/==)?fst/(==): ($465, $465) -> bool : (aa: V,aa: V) -> boolstd/core/types/bool: V, (@implicit/snd/==)?snd/(==): ($466, $466) -> bool : (bb: V,bb: V) -> boolstd/core/types/bool: V )result: -> total bool : boolstd/core/types/bool: V match mb1mb1: maybe2<$465,$466> Just2std/core/types/Just2: forall<a,b> (fst : a, snd : b) -> maybe2<a,b>(xx: $465,yy: $466) -> match mb2mb2: maybe2<$465,$466> Just2std/core/types/Just2: forall<a,b> (fst : a, snd : b) -> maybe2<a,b>(aa: $465,bb: $466) -> (xx: $465==?fst/(==): ($465, $465) -> boolaa: $465) &&std/core/types/(&&): (x : bool, y : bool) -> bool (yy: $466==?snd/(==): ($466, $466) -> boolbb: $466) Nothing2std/core/types/Nothing2: forall<a,b> maybe2<a,b> -> Falsestd/core/types/False: bool Nothing2std/core/types/Nothing2: forall<a,b> maybe2<a,b> -> match mb2mb2: maybe2<$465,$466> Nothing2std/core/types/Nothing2: forall<a,b> maybe2<a,b> -> Truestd/core/types/True: bool _ -> Falsestd/core/types/False: bool // Order on `:maybe` values pub fun cmpstd/core/maybe2/cmp: forall<a,b> (mb1 : maybe2<a,b>, mb2 : maybe2<a,b>, @implicit/fst/cmp : (a, a) -> order, @implicit/snd/cmp : (b, b) -> order) -> order( mb1mb1: maybe2<$560,$561> : maybe2std/core/types/maybe2: (V, V) -> V<aa: V,bb: V>, mb2mb2: maybe2<$560,$561> : maybe2std/core/types/maybe2: (V, V) -> V<aa: V,bb: V>, @implicit/fst/cmp?fst/cmp: ($560, $560) -> order : (aa: V,aa: V) -> orderstd/core/types/order: V, @implicit/snd/cmp?snd/cmp: ($561, $561) -> order : (bb: V,bb: V) -> orderstd/core/types/order: V)result: -> total order : orderstd/core/types/order: V match mb1mb1: maybe2<$560,$561> Just2std/core/types/Just2: forall<a,b> (fst : a, snd : b) -> maybe2<a,b>(xx: $560,yy: $561) -> match mb2mb2: maybe2<$560,$561> Just2std/core/types/Just2: forall<a,b> (fst : a, snd : b) -> maybe2<a,b>(aa: $560,bb: $561) -> match @implicit/fst/cmp?fst/cmp: ($560, $560) -> order(xx: $560,aa: $560) Eqstd/core/types/Eq: order -> @implicit/snd/cmp?snd/cmp: ($561, $561) -> order(yy: $561,bb: $561) lglg: order -> lglg: order Nothing2std/core/types/Nothing2: forall<a,b> maybe2<a,b> -> Gtstd/core/types/Gt: order Nothing2std/core/types/Nothing2: forall<a,b> maybe2<a,b> -> match mb2mb2: maybe2<$560,$561> Nothing2std/core/types/Nothing2: forall<a,b> maybe2<a,b> -> Eqstd/core/types/Eq: order _ -> Ltstd/core/types/Lt: order // Show a `:maybe2` type pub fun showstd/core/maybe2/show: forall<a,b,e> (mb : maybe2<a,b>, @implicit/fst/show : (a) -> e string, @implicit/snd/show : (b) -> e string) -> e string( mbmb: maybe2<$638,$639> : maybe2std/core/types/maybe2: (V, V) -> V<aa: V,bb: V>, @implicit/fst/show?fst/show: ($638) -> $640 string : aa: V -> ee: E stringstd/core/types/string: V, @implicit/snd/show?snd/show: ($639) -> $640 string : bb: V -> ee: E stringstd/core/types/string: V )result: -> 719 string : ee: E stringstd/core/types/string: V match mbmb: maybe2<$638,$639> Just2std/core/types/Just2: forall<a,b> (fst : a, snd : b) -> maybe2<a,b>(xx: $638,yy: $639) -> "Just2("literal: string
count= 6
++std/core/types/(++): (x : string, y : string) -> $640 string xx: $638.show?fst/show: ($638) -> $640 string ++std/core/types/(++): (x : string, y : string) -> $640 string ","literal: string
count= 1
++std/core/types/(++): (x : string, y : string) -> $640 string yy: $639.show?snd/show: ($639) -> $640 string ++std/core/types/(++): (x : string, y : string) -> $640 string ")"literal: string
count= 1
Nothing2std/core/types/Nothing2: forall<a,b> maybe2<a,b> -> "Nothing2"literal: string
count= 8
// Convert a `:maybe2` type to a boolean, equivalent to `is-just2`. pub fun boolstd/core/maybe2/bool: forall<a,b> (mb : maybe2<a,b>) -> bool( mbmb: maybe2<$738,$739> : maybe2std/core/types/maybe2: (V, V) -> V<aa: V,bb: V> )result: -> total bool : boolstd/core/types/bool: V match mbmb: maybe2<$738,$739> Just2std/core/types/Just2: forall<a,b> (fst : a, snd : b) -> maybe2<a,b> -> Truestd/core/types/True: bool Nothing2std/core/types/Nothing2: forall<a,b> maybe2<a,b> -> Falsestd/core/types/False: bool