Skip to content

Instantly share code, notes, and snippets.

@Jonplussed
Last active August 29, 2015 14:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jonplussed/5fc0a1a5c812bcb4a235 to your computer and use it in GitHub Desktop.
Save Jonplussed/5fc0a1a5c812bcb4a235 to your computer and use it in GitHub Desktop.
Add applicative `fmap` and monadic `bind` to Rust's builtin enums
trait MonadicOpt<T> {
fn fmap<U>(self, f: |T| -> U) -> Option<U>;
fn bind<U>(self, f: |T| -> Option<U>) -> Option<U>;
}
impl<T> MonadicOpt<T> for Option<T> {
fn fmap<U>(self, f: |T| -> U) -> Option<U> {
match self {
Some(x) => Some(f(x)),
_ => None,
}
}
fn bind<U>(self, f: |T| -> Option<U>) -> Option<U> {
match self {
Some(x) => f(x),
_ => None,
}
}
}
trait MonadicRes<T,E> {
fn fmap<U>(self, f: |T| -> U) -> Result<U,E>;
fn bind<U>(self, f: |T| -> Result<U,E>) -> Result<U,E>;
}
impl<T,E> MonadicRes<T,E> for Result<T,E> {
fn fmap<U>(self, f: |T| -> U) -> Result<U,E> {
match self {
Ok(x) => Ok(f(x)),
Err(e) => Err(e),
}
}
fn bind<U>(self, f: |T| -> Result<U,E>) -> Result<U,E> {
match self {
Ok(x) => f(x),
Err(e) => Err(e),
}
}
}
// ============================
// Example of using Option bind
// ============================
fn increment(n: int) -> Option<int> {
if n < 10 {
Some(n + 1)
} else {
None
}
}
fn display(n: int) -> Option<String> {
Some(n.to_string())
}
fn main() {
Some(1).bind(increment).bind(display); // => 2
Some(10).bind(increment).bind(display); // => None
None.bind(increment).bind(display); // => None
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment