2 ms·
This is kind of a pedantic distinction, but the behavior you've described is actually Functor behavior; I think Monads allow for Functor-like behavior as part o
by rybosome 12y ago
This is kind of a pedantic distinction, but the behavior you've described is actually Functor behavior; I think Monads allow for Functor-like behavior as part of their definition (not sure, I'm neither a category theorist nor an experienced Haskeller), but their use is something a little bit different. Monads allow you to do two things:
1) Lift regular values into monadic ones in a generic way. Let's say that we have two Monads - Optional and List. There should be a way such that we can take a non-monadic value (the part that will go inside) and turn it into a Monad. So, assuming Monad is a Java-like abstract class, the following should be possible:
Monad<String> m1 = Optional.lift("hello");
Monad<String> m2 = List.lift("hello");
2) Flat-map, typically called bind in this context. Given a monad and a function that takes a value and returns a monad, we should have some way of combining the resulting monads if we were to map this function over the first monad's internal value. So for instance, given an optional string, and a function that takes a string and returns an optional int, we should have some way of combining the Optional<Optional<Integer>> into just an Optional<Integer>. So, in the following contrived example...
// Returns a UTF8 string value from a database, may fail
public Optional<String> getUtf8Name() { ... }
// Returns the length of a String if it contains exclusively ascii characters
public Optional<Integer> getAsciiLength(String str) { ... }
... you can compare the differences between it and the Functor's map:
Optional<Integer> asciiLength = getUtf8Name().bind(getAsciiLength);
Optional<Integer> otherAsciiLength = getUtf8Name().map(getAsciiLength).getOrElse(Optional.absent());
As it turns out, you can implement the Functor's map method in a generic way using lift and bind.
public abstract class Monad<A> implements Functor<A> {
/**
* Implements Functor's map method.
*/
@Override
public <B> Monad<B> map(Function<A, B> fn) {
return this.bind( innerValue -> this.lift(fn.apply(innerValue)) );
}
}
- Paradigma11 12y agoMonad<String> m1 = Optional.lift("hello"); Monad<String> m2 = List.lift("hello"); Shouldn't that be Option<String> m1 = Optional.lift("hello"); List<String> m2 = List.lift("hello"); ?