+
+## Acknowledgements ##
+
+Our library is largely based on the mtl library distributed with the Haskell Platform. That in turn was inspired by Mark Jones' 1995 paper
+[Functional Programming with Overloading and Higher-Order Polymorphism](http://web.cecs.pdx.edu/~mpj/pubs/springschool.html).
+
+I've also been helped in various ways by posts and direct feedback from Oleg Kiselyov and Chung-chieh Shan. The following were also useful:
+
+ * <http://pauillac.inria.fr/~xleroy/mpri/progfunc/>
+ * Ken Shan "Monads for natural language semantics" <http://arxiv.org/abs/cs/0205026v1>
+ * <http://www.grabmueller.de/martin/www/pub/Transformers.pdf>
+ * <http://en.wikibooks.org/wiki/Haskell/Monad_transformers>
+
+
+## Comparisons with Haskell ##
+
+Some comparisons with the Haskell monadic libraries, which Juli8 mostly follows.
+
+In Haskell, the `'a Reader.t` monadic type would be defined something like this:
+
+ newtype Reader a = Reader { runReader :: env -> a }
+
+(For simplicity, I'm suppressing the fact that `Reader` is also parameterized
+on what type `env` is.) This creates a type wrapper around `env -> a`, so that Haskell will
+distinguish between values that have been specifically designated as
+being of type `Reader a`, and common-garden values of type `env -> a`.
+
+To lift an aribtrary expression `E` of type `env -> a` into an `Reader a`,
+you do this:
+
+ Reader { runReader = E }
+
+or use any of the following equivalent shorthands:
+
+ Reader (E)
+ Reader $ E
+
+To drop an expression `R` of type `Reader a` back into an `env -> a`, you do
+one of these:
+
+ runReader (R)
+ runReader $ R
+
+The `newtype` in the type declaration ensures that Haskell does this all
+efficiently: though it regards `E` and `R` as type-distinct, their underlying
+machine implementation is identical and doesn't need to be transformed when
+lifting/dropping from one type to the other.
+
+Now, you _could_ also declare monads as record types in OCaml, too, _but_
+doing so would introduce an extra level of machine representation, and
+lifting/dropping from the one type to the other wouldn't be free like it is
+in Haskell. Also it would be syntactically more complex.
+
+So Juli8 instead encapsulates the monadic values by making their implementation types "private" or abstract or opaque. We get the same result: OCaml won't let you freely interchange `'a Reader.t`s with `env -> 'a`s. The Juli8 internals can see that these are equivalent, but refuses to permit code outside of the library to rely on that assumption. Instead, you have to use the `run` operation (like Haskell's `runReader`) to convert the opaque monadic values to ones whose type is exposed to you.