4 ms·
Monad is a pattern for constructing container types so that their instances can be used in chain operations safely. Given a value type, you can build a monad ty
by ww520 1y ago
Monad is a pattern for constructing container types so that their instances can be used in chain operations safely. Given a value type, you can build a monad type wrapping the value type with a set of prescribed monadic functions. Instances of the monad type are called monadic values.
Example is best for illustration. I'll use a made-up syntax.
// 'Maybe' is a monad wrapping any value type T that can be null.
class Maybe<T> {
// The value wrapped by the monadic value
value: T;
// A constructor to make a Maybe monadic value from a plain value T.
// This is called 'unit' or 'return' in Haskell, or 'lift' in other languages.
// It's really a constructor.
static wrap(v: T) Maybe<T> {
return new Maybe { value = v }
}
// then() applies fn on the unwrapped value. fn returns a Maybe<T>.
// This is called 'bind' in Haskell, or 'flatMap' in other languages.
then(fn: (T) => Maybe<T>) Maybe<T> {
return this.value == null ? Maybe.wrap(null) : fn(this.value);
}
}
That's it! That's all to to monad. You can use the same pattern to build other monadic types, like List<T>, Promise<T>, IO<T>, as long as the wrap() and then() functions are built accordingly. Back to this example, to use it,
let a = Maybe<int>.wrap(4) // construct a monadic value
let b = a.then(x => Maybe<int>.wrap(x + 1)) // add 1 to it
let c = Maybe<int>.wrap(null) // construct a null monadic value
let d = c.then(x => Maybe<int>.wrap(x + 1)) // safely handle null; d is null
let e = Maybe<int>.wrap(5)
.then(x => Maybe<int>.wrap(x + 1))
.then(x => Maybe<int>.wrap(x * 2)) // chain the calls
let f = Maybe<float>.wrap(5.0) // The same Maybe on a different type
.then(x => Maybe<float>.wrap(null))
.then(x => Maybe<float>.wrap(x * 2)) // chain the calls; safely handle null
- 1718627440 1y agoWhy does it sound so complicated when it is just a wrapper type that conforms to an interface?
- ww520 1y agoIt is what you described at high level. The devils are in the detail. People keep using words to describe the detail when code shows everything.
- yobbo 1y agoIt's a generalised typeclass for wrappers. It's not called "then" but "bind" and spelled (>>=), which doesn't exactly evoke useful associations for newcomers.
- immibis 1y agoBecause the interface has a few complicated rules associated with it. If you break them, the compiler may accept your code but it won't work with a lot of libraries that are supposed to work with any monad.