add elevate laws
[lambda.git] / monad_transformers.mdwn
index 0e9d928..a1e6d45 100644 (file)
@@ -116,6 +116,10 @@ Then if you want to use an `S`-specific monad like `puts succ` inside `MS`, you'
 
        # MS.(...elevate (S.puts succ) ...)
 
+Each monad transformer's `elevate` function will be defined differently. They have to obey the following laws:
+
+*      `Outer.elevate (Inner.unit a) <~~> Outer.unit a`
+*      `Outer.elevate (Inner.bind u f) <~~> Outer.bind (Outer.elevate u) (fun a -> Outer.elevate (f a))`
 
 We said that when T encloses M, you can rely on T's interface to be most exposed. That is intuitive. What you cannot also assume is that the implementing type has a Tish structure surrounding an Mish structure. Often it will be reverse: a ListT(Maybe) is implemented by a `'a list option`, not by an `'a option list`. Until you've tried to write the code to a monadic transformer library yourself, this will probably remain counter-intuitive. But you don't need to concern yourself with it in practise. Think of what you have as a ListT(Maybe); don't worry about whether the underlying implementation is as an `'a list option` or an `'a option list` or as something more complicated.