(* use this via open Either.Cons *)
signature EITHER_CONS =
sig
datatype ('left, 'right) either = INL of 'left | INR of 'right
end
signature EITHER =
sig
include EITHER_CONS
structure Cons : EITHER_CONS
val isLeft : ('left, 'right) either -> bool
val isRight : ('left, 'right) either -> bool
val asLeft : ('left, 'right) either -> 'left option
val asRight : ('left, 'right) either -> 'right option
val map : ('ldom -> 'lrng) * ('rdom -> 'rrng)
-> ('ldom, 'rdom) either
-> ('lrng, 'rrng) either
val app : ('left -> unit) * ('right -> unit)
-> ('left, 'right) either
-> unit
val fold : ('left * 'b -> 'b) * ('right * 'b -> 'b)
-> 'b
-> ('left, 'right) either
-> 'b
val proj : ('a, 'a) either -> 'a
val partition : (('left, 'right) either) list
-> ('left list * 'right list)
val mapLeft : ('ldom -> 'lrng)
-> ('ldom, 'rdom) either
-> ('lrng, 'rdom) either
val mapRight : ('rdom -> 'rrng)
-> ('ldom, 'rdom) either
-> ('ldom, 'rrng) either
val appLeft : ('left -> unit)
-> ('left, 'right) either
-> unit
val appRight : ('right -> unit)
-> ('left, 'right) either
-> unit
val bindRight : ('a -> ('left, 'b) either)
-> ('left, 'a) either
-> ('left, 'b) either
val bindLeft : ('a -> ('b, 'right) either)
-> ('a, 'right) either
-> ('b, 'right) either
val fromOption : 'l
-> 'r option
-> ('l, 'r) either
end
This project started originally as John Reppy's Either module added as an smlpkg package. Based on the original BasisLibrary 2015-002 submission, but packaged to be accessible to the wider smlpkg ecosystem. Subsequently, the openable constructor addition was made for better ergonomics.
It's nice to be able to use Either's constructors (INR and INL) without
prefixing, just like one can use SOME and NONE in the Basis library.
The problem with openining Either as-is is that there are several functions
in there that shadow standard Basis functions like map and app.
I wanted to be able to open the constructors only, while leaving the other functions
fully-prefixed. The solution I came up with is to define a separate signature
EITHER_CONS, which exposes only the constructors, and subsequently both open it in
the implementation and expose it as a member struct. So now you can:
> val prefixed_val = Either.INR 3;
val prefixed_val = INR 3: ('a, int) Either.either
> open Either.Cons;
datatype ('a, 'b) either = INL of 'a | INR of 'b
> val non_prefixed_val = INR 3;
val non_prefixed_val = INR 3: ('a, int) either
> prefixed_val = non_prefixed_val;
val it = true: bool
- Place the package in your
sml.pkgfile;
require {
github.com/pzel/sml-either 0.0.1
}
- Sync with upstream
smlpkg sync
- If everything goes well, you'll have
either.mlbin thelibhierarchy:
$ find lib/ | grep either.mlb
lib/github.com/pzel/sml-either/either.mlb
- Run tests & build under mlton
- Run tests & build under poly(mlb)
- Set up CI