3 ms·
To start with, Functor gives an generic interface (fmap) allowing you to take Foo<A> and a function B f(A) and apply it to get Foo<B> Then mon
by axman6 13y ago
To start with, Functor gives an generic interface (fmap) allowing you to take
Foo<A>
and a function
B f(A)
and apply it to get
Foo<B>
Then monad gives us something called join, which lets us take:
Foo<Foo<A>>
and turn it into
Foo<A>
It's pretty obvious that a Vector of Vectors of A's can be turned into a Vector of A's by concatenating them into one Vector. Also optional (something I don't know much about, sorry) can be turned from Optional<Optional<A>> into Optional<A> if the outer actually contains an inner optional, and the inner optional contains an A.
So with these two things, we can do things like:
Vector<B> f(A);
Vector<C> g(B)
Vector<A> foos = {a,b,c};
foos.fmap(f).join().fmap(g).join()
to get a Vector<C>. The result is basically considered all possible results of applying f to all the values in foos, and then applying g to all the values returned by all the calls to f. this is the non-deteminism monad, where each function f and g can produce multiple results (including none) for each input, and we can chain multiple non-deterministic computations to get all the non-deterministic results.
Usually Mopnad is explained with return and bind, but I think it's a bit less obvious. But I'll give it a shot...
bind in Haskell is something that takes something of type
Foo<A>
and a function with type
Foo<B> f(A)
and produces something of type
Foo<B>
From above, we can rewrite the example with
Vector<B> f(A)
Vector<C> g(B>
Vector<A> foos = {a,b,c};
foos.bind(f).bind(g);
and get the same result as before. I guess you could use slightly cleaner syntax (why the hell not overload >> for yet another bizarre use right? [leading to foos >> f >> g;])
I hope that you can see that this is just a simple interface which can work for many types that look like Foo<a> (Vector, Set [assuming C++ has that?], Optional, even pointers to some extent; see the discussions of the introduction of "?." into C# which is exactly what the Maybe monad encodes). There are also plenty of other monads in the haskell universe which aren't as easy to show in C++ because a) I'm not sure C++'s type system is up to it and b) my C++ knowledge is not strong enough to demonstrate things like the State monad, and definitely the Cont[inuation] monad.
Anyway, bring it back to the topic of the article, it should be clear that something of type
Future<A>
can be composed with other functions w3hich produce more Futures:
Future<B> f(A);
Future<C> g(B);
Future<A> async_A("thing");
asyc_A.bind(f).bind(g);
Which handles all the unwrap and passing of values "inside" the future to each consecutive function.
I know this isn't a concise explanation, but it's because it's a very simple, but also very abstract idea, and its best introduced with example uses, then generalising it.
- eru 13y agoGood explanation. To add, you have (at least) two choices to implement Monads for Vectors. The one you explained is akin to the standard Haskell List Monad, and the other one is the ZipList.