Closed jonsterling closed 9 years ago
I am a big fan of m (Either l r)
although I could see how an EitherT
might add convenience in this case.
Yes, I am coming to think that m (Either l r)
provides a good sweet spot, which is readily composed with other code without introducing too many constraints on the environment. Thanks for your input @gregwebs!
I think that code that doesn't use anything but left
and right
from EitherT
, could as well be kept in MonadError
, since there is really no reason to not just use throwError
and return
. The benefit is that it seamlessly composes with Either
and EitherT
(and also Except
, ExceptT
, and even the maybe flavored monads, if really needed).
Also, I switch to preferring ExceptT
over EitherT
, since it is in transformers now and widely portable without introducing extra dependencies from the Edward Kmett universe.
ExceptT
(transformers) dependencies:
library
build-depends: base >= 2 && < 6
EitherT
(either) dependencies:
library
build-depends:
base >= 4 && < 5,
bifunctors >= 4 && < 5,
exceptions >= 0.5 && < 0.9,
free >= 4.9 && < 5,
monad-control >= 0.3.2 && < 1.1,
MonadRandom >= 0.1 && < 0.4,
mtl >= 2.0 && < 2.3,
profunctors >= 4 && < 5,
semigroups >= 0.8.3.1 && < 1,
semigroupoids >= 4 && < 5,
transformers >= 0.2 && < 0.5,
transformers-base >= 0.4 && < 0.5
@larskuhtz I have found difficulty in convincing the compiler that a MonadError
is in fact an EitherT
. I will ask for your help next time.
@gregwebs that would be interesting. As long as there is an MonadError
instance for EitherT
the compiler should have really no trouble to instantiate anything with MonadError
.
In my experience things usually only get painful when doing things like (a) changing the error type (although there a a few tricks that are not too bad) or (b) passing around functions with a parameterized and constraint context on the return type.
Thanks for the note about ExceptT
; I repeatedly forget about this one... If I end up using a transformer, I'll use ExceptT
, though I am leaning toward what Greg suggested before...
I found that most of the time, the only functions from EitherT
that I am missing for ExceptT
are fmapLT
and exceptT
. Both trivial enough to just define them in place and don't really justify the extra dependencies of EitherT
.
Resolved by #20
Requiring code that calls the Kinesis producer (or consumer) to live inside
MonadError ConsumerError
orMonadError ProducerError
is honestly too much to swallow. Makes things very difficult to compose. Originally, I'd sort of designed it as a little DSL where you wouldn't even have to refer to the producer or consumer object by name, but that ship sailed a long time ago; it just doesn't scale up.The obvious way forward is to return something like
EitherT ConsumerError m a
in the calls to the producer and consumer (or justm (Either ConsumerError a)
). Alternative proposals are welcome.