|
Boost : |
From: Brian McNamara (lorgon_at_[hidden])
Date: 2003-10-17 22:06:08
On Fri, Oct 17, 2003 at 04:55:12PM -0400, David Abrahams wrote:
> Brian McNamara <lorgon_at_[hidden]> writes:
> > The documentation is available at
> > http://www.cc.gatech.edu/~yannis/fc++/boostpaper/
> > in a few different formats.
>
> Brian, I'm following the documentation links for Monads to
> http://www.cc.gatech.edu/~yannis/fc++/fcpp-lambda.pdf, and reading
> along... I arrive at:
>
> class Monad m where
> bind :: m a -> ( a -> m b ) -> m b
> unit :: a -> m a
>
> And note that you haven't introduced the syntax 'm a' anywhere. I
> understand that to be function invocation in other contexts (without
> help from the paper which it should probably give), but I don't
> understand how to read it here.
>
> Can you help?
Yes.
As you mentioned, you've already figured out that in the "value" domain,
this syntax is used for function application. That is
Haskell C++
------- === ------- // all of these expressions
f x f(x) // reduce to values
g x y g(x,y)
In the "type" domain, this same syntax is used for type-function
application, that is, templates:
Haskell C++
------- === ------- // all of these "expressions"
f x f<x> // reduce to types
g x y g<x,y>
For example, in C++, if we have the template "list" (as in "list<int>"),
then "list" is a type function of one argument--you pass it a type (like
"int"), and it returns you a type ("list<int>"). std::map is a
two-argument type function; you pass it a key type and a value type, and
it returns you a class which is specialized for those types (e.g. a
map<string,int>).
So, returning to the concrete example at hand:
bind :: m a -> ( a -> m b ) -> m b
unit :: a -> m a
Here 'm' is a "type constructor" (a one-argument function from types to
types), and thus "m a" is a normal datatype.
It might be helpful to think of this
bind :: m a -> ( a -> m b ) -> m b
as being analogous to
template <template <class> class M, class A, class B>
M<B> bind( M<A>, fcpp::fun1< A, M<B> > );
where M is realized as a template-template parameter. (The actual
FC++ implementation is done in a completely different way; this example
is just for purpose of exposition.)
To make things even more concrete, knowing that the general monad
signature for unit is
unit :: a -> m a
consider these actual examples of FC++ code:
list_m::unit( 3 ) // a value whose type is list<int>
maybe_m::unit( 3 ) // a value whose type is maybe<int>
Thus, in the list monad (represented by class fcpp::list_m in FC++),
"m==fcpp::list" whereas in the maybe monad (class fcpp::maybe_m),
"m==fcpp::maybe".
Hope that helps some; I feel like that was awfully long-winded.
-- -Brian McNamara (lorgon_at_[hidden])
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk