
On Saturday 29 May 2010 01:28:59, Ivan Lazar Miljenovic wrote:
Daniel Fischer
writes: On Friday 28 May 2010 20:44:20, Donn Cave wrote:
Quoth Vo Minh Thu
, ... Control.Monad.Error provides an instance for Either.
... in the mtl transformer library, in case anyone else besides myself didn't know that. And I see it has to be there because it depends on the Error typeclass.
Which is considered a wart by some. (Either left) has a perfectly valid Monad instance for any type left (the only slightly difficult thing might be 'fail').
Though how would you set the Left value for some arbitrary type?
That is the difficult thing. If you want to have instance Monad (Either e) where ... , there are only two possibilities for fail that I see, fail msg = error msg -- or error somethingElse fail msg = Left undefined -- or Left (error msg) Neither is entirely convincing, but the second is a little more robust (though you can't inspect failures without catching exceptions). Constructing more meaningful Left values is then a little dangerous (if you try to inspect them) or pointless (if not). But if you want to have instance Monad (Either ConcreteType) where ... , you can have fail msg = Left someDefaultValue (or let the value depend on the message) and you can construct Left someMeaningfulValue in concrete situations. Of course, you can then also write instance Error ConcreteType where noMsg = someDefaultValue strMsg msg = whatever which really is no more fuss, so the 'bad' thing about it is just that if you want a Monad instance for (Either ConcreteType), you have to - import Control.Monad.Error(.Class) and make ConcreteType an instance of Error, or - make sure it's never used in the same module as C.M.E, or - enable OverlappingInstances when they're used together. Need I explain why I prefer the first?
Though I can't really be sure what the documentation is trying to say.)
In that case, have a look at the code, perhaps that is clearer. (And bug the maintainer(s) to improve the docs.)
IIRC, the basic point is that the Left type has to be one which can be converted from some arbitrary String value, to take into account the fail method for that type:
fail :: (Monad m) => String -> m a
Yep.