From: james woodyatt <jhw@wetware.com>
To: The Trade <caml-list@inria.fr>
Cc: Ocaml Beginners <ocaml_beginners@yahoogroups.com>
Subject: [Caml-list] monads for dummies
Date: Wed, 12 Mar 2003 16:03:19 -0800 [thread overview]
Message-ID: <3273E2D8-54E7-11D7-97B5-000393BA7EBA@wetware.com> (raw)
In-Reply-To: <3E6DDAFC.19000.44771B6@localhost>
[followups redirected to ocaml_beginners@yahoogroups.com]
On Tuesday, Mar 11, 2003, at 11:47 US/Pacific, mgushee@havenrock.com
wrote:
>
> [...] My other big problem with Haskell was ... you guessed it:
> monads! I
> must have read every introduction to monads that's available on line
> (and there are at least half a dozen), but I still don't really
> understand them. [...]
I'm a self-taught "programmer" with no formal education in mathematics
or computer science, and I found the monad concept to be fairly
difficult to learn. It took a leap of consciousness that feels about
the same level of difficulty as what I remember needing to get through
my high school calculus class.
I've been seeing a lot of attempts to explain the theory lately, but
most of them remind me of the kind of thing that I found more confusing
than helpful when I was trying to get my head around the practical
matters. What I really wanted is a Monads For Dummies tutorial.
Here's what I remember being the crucial tip that got me over the hump:
if you are working with immutable data structures (and there are at
least three in the Ocaml standard library: Map, Set and List), then the
monadic programming style can be really useful for composing
complicated functions for manipulating the contents of those data
structures from assemblies of simpler functions.
Without the monadic programming style, you end up concocting huge
specialized functions for passing into the higher-order standard
library functions, e.g. fold, map, filter, etc., and achieving any kind
of modularity requires careful design work. The problem can quickly
become hard enough that learning monadic programming starts to seem
like a decent trade.
Once you start using immutable data structures in complex ways (e.g.
doing lots of weird transformations on 'a list values), you may find
that writing your functions as monads will help you modularize your
program, allowing you to encapsulate and reuse computations that would
otherwise be duplicated in scattered fragments of code all over the
place. (Alternatively, you may want to use mutable data structures
instead, which is always a popular way out of this problem.)
If you discover your immutable data structure manipulations are getting
out of hand, and you want to reorganize your code for better
encapsulation and reusability-- without changing them to use mutable
data structures instead-- then I recommend learning about the
continuation monad first.
Here is the signature of a module I use for the continuation monad in
Ocaml:
type ('x, 'a) t = ('a -> 'x) -> 'x
(* let ( >>= ) m f x = m (fun a -> f a x) *)
val ( >>= ): ('x, 'a) t -> ('a -> ('x, 'b) t) -> ('x, 'b) t
val return: 'a -> ('x, 'a) t (* let return x f = f x
*)
val lift: 'x -> ('x, 'a) t (* let lift x _ = x
*)
val cont: ('x -> 'x) -> ('x, unit) t (* let cont f g = f (g ())
*)
val eval: ('x, unit) t -> 'x -> 'x (* let eval m x = m (fun () ->
x) *)
By using this module, I can make new continuations (functions of type
'x -> 'x) by composing appropriate instances of the continuation monad
type and binding them with functions that chain the results of previous
computations into the subsequent computations.
For a very simple example: if you have a bunch of continuation
functions, e.g. f1, f2, f3 each of type 'x -> 'x, then you can compose
them in sequence like so:
let m: ('x, unit) t =
cont f1 >>= fun _ ->
cont f2 >>= fun _ ->
cont f3
In fact, it might be easier to represent f1, f2 and f3 as their monads
to begin with:
let m1: ('x, unit) t = cont f1
let m2: ('x, unit) t = cont f2
let m2: ('x, unit) t = cont f3
let m: ('x, unit) t =
m1 >>= fun _ ->
m2 >>= fun _ ->
m3
This defines a new instance of the continuation monad type, but it
isn't exactly the composed continuation function yet. You *evaluate*
the monad to get the continuation it represents:
let f: 'x -> 'x = eval m
The 'return' function is also sometimes called the 'unit' function (but
'unit' is a reserved word in Ocaml, so I like to avoid it). It
constructs a monad that passes a value through the ( >>= ) operator to
the function that constructs a new monad value with it. It's good for
use in monad functions that take input from "outside" the encapsulation
and pass it along to other monads.
The 'lift' function is a variant of the 'cont' function which ignores
the 'x value that is input from any previous computation and produces
the 'lifted' value as output. It's good for use in monad functions
that initialize (or reinitialize) the encapsulated value of the monad.
I probably should have named it 'init' instead.
If I were writing a book on using monads for dummies, I'd launch here
into a series of useful examples showing how to use monads to simplify
very complicated list manipulation functions. The example above is too
simple to show the power of monadic programming adequately. I don't
have the time, but it's certainly something that needs to be done.
The continuation monad is only the beginning. There are several
fundamental types of monad, and it's possible to combine them into
composites to support more operations, e.g. state manipulation,
exception handling, backtracking, etc. Once you understand how to use
monads in a systematic design, you can take better advantage of the
support for pure functional programming available in the Ocaml language.
In lieu of my writing a long list of examples, here is a paper that I
found immensely helpful in the learning process:
<http://www.math.chalmers.se/~augustss/AFP/monads.html>
The examples are written in Haskell, but I found them pretty easy to
translate in my head to the equivalent Ocaml.
Warning: you don't have to go down this path very far before you will
begin to chafe at the "operator overloading" problem. You can't define
a ( >>= ) operator that will be good for all monad types. I don't know
how to explain exactly why. You just can't. Some folks have proposed
that "extensional polymorphism" would be very helpful in helping solve
the problem. I buy that.
Warning2: since Ocaml strictly evaluates all the arguments to a
function before executing it (unless the argument is of type 'a
Lazy.t), you really can't define a proper ( >> ) operator for your
monads. It won't work the same as the one in Haskell, because Ocaml
evaluates the right operand before it's needed, and you don't buy
anything by fixing it so that it takes a Lazy.t value instead.
If what I've written isn't very helpful to you, then please tell me so
I know not to try to explain this stuff to people. On the other hand,
if it *is* helpful, that would be nice to know too.
--
j h woodyatt <jhw@wetware.com>
that's my village calling... no doubt, they want their idiot back.
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
next prev parent reply other threads:[~2003-03-13 1:04 UTC|newest]
Thread overview: 88+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-03-06 23:27 [Caml-list] OCaml popularity Graham Guttocks
2003-03-10 20:43 ` Paul Steckler
2003-03-10 23:48 ` Gerd Stolpmann
2003-03-11 0:18 ` Brian Hurt
2003-03-17 23:49 ` Graham Guttocks
2003-03-11 1:43 ` Nicolas Cannasse
2003-03-11 10:23 ` Pierre Weis
2003-03-11 14:27 ` Guillaume Marceau
2003-03-11 16:16 ` David Brown
2003-03-11 16:47 ` [Caml-list] about -rectypes Christophe Raffalli
2003-03-12 2:32 ` [Caml-list] OCaml popularity Nicolas Cannasse
2003-03-12 3:55 ` Cross-platform GUI (was Re: [Caml-list] OCaml popularity) mgushee
2003-03-12 10:51 ` [Caml-list] OCaml popularity Alex Romadinoff
2003-03-12 18:24 ` Max Kirillov
2003-03-11 19:02 ` Graham Guttocks
2003-03-12 17:12 ` Richard W.M. Jones
2003-03-12 18:08 ` Alwyn Goodloe
2003-03-12 22:34 ` Michael Schuerig
2003-03-12 23:13 ` Martin Weber
2003-03-12 23:35 ` Michael Schuerig
2003-03-13 8:02 ` Alessandro Baretta
2003-03-13 10:23 ` Michael Schuerig
2003-03-12 23:35 ` Brian Hurt
2003-03-12 23:18 ` Daniel Bünzli
2003-03-12 23:47 ` Brian Hurt
2003-03-13 2:15 ` William Lovas
2003-03-13 3:44 ` Graham Guttocks
2003-03-13 9:31 ` Richard W.M. Jones
[not found] ` <20030313095232.GC347@first.in-berlin.de>
2003-03-13 20:50 ` William Lovas
2003-03-13 21:17 ` Oliver Bandel
2003-03-13 22:01 ` Brian Hurt
2003-03-13 22:17 ` Oliver Bandel
2003-03-14 6:33 ` Michal Moskal
2003-03-14 11:50 ` Markus Mottl
2003-03-14 15:38 ` Oliver Bandel
2003-03-14 10:13 ` MikhailFedotov
2003-03-14 10:30 ` Johann Spies
2003-03-13 8:09 ` Pierre Weis
2003-03-15 1:43 ` Tushar Samant
2003-03-15 8:19 ` Andreas Eder
2003-03-11 16:26 ` Fred Yankowski
2003-03-11 19:47 ` [Caml-list] OCaml popularity (long!) mgushee
2003-03-12 11:23 ` Diego Olivier Fernandez Pons
2003-03-30 5:59 ` Belated thanks (was Re: [Caml-list] OCaml popularity) Matt Gushee
2003-03-31 15:27 ` [Caml-list] Re: Belated thanks cashin
2003-04-01 8:22 ` Belated thanks (was Re: [Caml-list] OCaml popularity) Johann Spies
2003-03-12 20:41 ` [Caml-list] OCaml popularity (long!) Max Kirillov
2003-03-13 2:36 ` Haskell-like syntax (was: [Caml-list] OCaml popularity (long!)) Oleg
2003-03-13 18:33 ` [Caml-list] Re: Haskell-like syntax Max Kirillov
2003-03-14 19:30 ` Max Kirillov
2003-03-14 19:47 ` Max Kirillov
2003-03-14 20:01 ` Seth Kurtzberg
2003-03-14 20:34 ` brogoff
2003-03-14 21:17 ` Sebastien Carlier
2003-03-14 21:51 ` brogoff
2003-03-15 2:27 ` Max Kirillov
2003-03-15 10:58 ` Markus Mottl
2003-03-15 15:52 ` [Caml-list] globally valid symbols (was: Haskell-like syntax) Max Kirillov
2003-03-15 20:16 ` [Caml-list] Re: Haskell-like syntax David Brown
2003-03-16 5:28 ` Module recursion (Was Re: [Caml-list] Re: Haskell-like syntax) brogoff
2003-03-16 11:10 ` Markus Mottl
2003-03-16 18:02 ` brogoff
2003-03-16 18:34 ` Markus Mottl
[not found] ` <Pine.LNX.4.44.0303152112560.27230-100000@grace.speakeasy.n et>
2003-03-16 5:38 ` Chris Hecker
2003-03-16 18:34 ` brogoff
2003-03-17 2:20 ` Jacques Garrigue
[not found] ` <Pine.LNX.4.44.0303161020480.11736-100000@grace.speakeasy.n et>
2003-03-17 5:08 ` Chris Hecker
2003-03-17 17:06 ` brogoff
2003-03-17 19:01 ` Ville-Pertti Keinonen
[not found] ` <Pine.LNX.4.44.0303170836240.29039-100000@grace.speakeasy.n et>
2003-03-17 19:33 ` Chris Hecker
2003-03-17 20:28 ` brogoff
[not found] ` <Pine.LNX.4.44.0303171145500.29039-100000@grace.speakeasy.n et>
2003-03-17 21:09 ` Chris Hecker
2003-03-19 2:34 ` [Caml-list] ocamlopt speed (was Re: Module recursion) Chris Hecker
2003-03-19 10:03 ` Michal Moskal
2003-03-19 10:38 ` Gerd Stolpmann
2003-03-19 20:36 ` Chris Hecker
2003-03-17 1:46 ` [Caml-list] Re: Haskell-like syntax Nicolas Cannasse
2003-03-14 22:50 ` Oleg
2003-03-20 15:01 ` Andreas Rossberg
2003-03-12 20:46 ` [Caml-list] Monads was OCaml popularity Christophe Raffalli
2003-03-13 0:03 ` james woodyatt [this message]
2003-03-13 4:32 ` [Caml-list] monads for dummies Christopher Quinn
2003-03-13 11:53 ` Christian Lindig
2003-03-12 18:59 ` [Caml-list] OCaml popularity Martin Weber
2003-03-12 20:24 ` Xavier Leroy
2003-03-13 8:57 ` [Caml-list] how to interface with integer Bigarrays using camlidl francois bereux
2003-03-13 9:36 ` Xavier Leroy
2003-03-13 0:42 ` [Caml-list] OCaml popularity Graham Guttocks
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3273E2D8-54E7-11D7-97B5-000393BA7EBA@wetware.com \
--to=jhw@wetware.com \
--cc=caml-list@inria.fr \
--cc=ocaml_beginners@yahoogroups.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).