Skip to content

Instantly share code, notes, and snippets.

@gavinking
Last active March 26, 2016 10:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gavinking/fb923d11893503318ac8 to your computer and use it in GitHub Desktop.
Save gavinking/fb923d11893503318ac8 to your computer and use it in GitHub Desktop.
Emulating the Maybe monad in Ceylon
/*
Demonstrates how to do monadic-style processing of
optional values in Ceylon. Represents an optional
type by boxing non-null values as singletons, and
the null value as the empty sequence. Monadic
operations are inherited from the stream interface,
with the caveat that m.flatMap(f) must be written
as m.flatMap(lift(f)) or as m.map(f).coalesced.
For the record: this is not idiomatic Ceylon. In
Ceylon, optional values are represented in a more
efficient unboxed form using a union type of form
T|Null.
*/
"The type of boxed optional values."
alias Maybe<X>
given X satisfies Object
=> [X]|[];
"A function to box an optional value.
(Just an alias for the built-in
function emptyOrSingleton().)"
Maybe<X> maybe<X>(X? x)
given X satisfies Object
=> emptyOrSingleton(x);
"A higher order function to lift a
function that returns an optional
value. The resulting function
returns boxed optional values."
Maybe<X>(Y) lift<X,Y>(X?(Y) f)
given X satisfies Object
=> compose(maybe<X>, f);
shared void run() {
value arg = maybe(process.arguments[0]);
//using lift()
arg.map(String.trimmed)
.flatMap(lift(parseInteger))
.each(print);
//alternatively
arg.map(String.trimmed)
.map(parseInteger).coalesced
.each(print);
//using a comprehension
{ for (a in arg)
for (t in maybe(a.trimmed))
for (p in maybe(parseInteger(t)))
p }
.each(print);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment