result and pointFreeVersion must be refactored as well, fortunately you can use ReaderEither's monadic interface
// before constresult=pipe(E.right('foo'),E.chain(f),E.map(g),E.chain(h))constpointFreeVersion=flow(f,E.map(g),E.chain(h))// afterconstresult=pipe(RE.right('foo'),RE.chain(f),RE.map(g),RE.chain(b=>RE.fromEither(h(b))))constpointFreeVersion=flow(f,RE.map(g),RE.chain(b=>RE.fromEither(h(b))))
There's a benefit in using the monadic interface though: software is written in a uniform style, regardless of the effect.
I was just about to say it: I think main benefit is (ironically) readability - by saying explicitly Reader<Dependencies, string> you clearly communicate your intent (assuming others know the concept as well, of course 😄).
There's a benefit in using the monadic interface though: software is written in a uniform style, regardless of the effect.
You can think of
Reader
as an effect, muck likeEither
orTask
.Let's say you have the following snippet
and at some point you must refactor
f
toresult
andpointFreeVersion
must be refactored as well, fortunately you can useReaderEither
's monadic interfaceI was just about to say it: I think main benefit is (ironically) readability - by saying explicitly
Reader<Dependencies, string>
you clearly communicate your intent (assuming others know the concept as well, of course 😄).That's right, you write programs by composing kleisli arrows
A -> M<B>
, for some effectM
.So
Reader
(orReaderEither
,ReaderTaskEither
,Option
,Either
, etc...) is just one of the possible effects