R<E1,R<E2,A>> -- flatten --> R<E1 + E2, A>
R stands for result, E1,E2 are errors.You need to think up a reasonable implementation of +. This is of course easily solvable, you can just add them together. Keep a list of errors in your result instead of one error and you are done. Just keep the +, it is free :p
Validation types work the way you describe and require a monoidal "error" side, but famously do not form monads (though they are applicative functors).
But of left identity, right identity, and associativity, what is violated?
No flattening doesn't make something a monad. Return and flattening are the interesting operations of a monad, that together with the laws makes the monad.
>But of left identity, right identity, and associativity, what is violated?
Well, there is not something violated perse, but you cannot write a flatten operation for something like this:
R<R<u32, E1>, E2>
However you could write it for this: R<R<u32, E1 + E2>, E1 + E2>
(That was what I should have written above btw) Because now the error types are the same.Result<T> instead of Result<T,E> so that it was easier to compose.
This made Kleisli composition easier since I don't have to worry about mismatched types on the Error.
You can see the code at https://github.com/brennancheung/wasmtalk/blob/master/src/fp...