haskell - difference between two monads: ErrorT e Identity v and Either e v -
can explain difference between
errort string identity integer
and either string integer
?
(to simplify this, i'm going answer in terms of exceptt
type instead of the deprecated errort
. answer not strictly true errort
, it's true modulo annoying facts led deprecation of errort
.)
the key concept understand here isomorphism. put very informally, 2 types isomorphic when, in spite of being superficially different, "essentially same."
we can put bit more meat on notion adding concept: 2 haskell types isomorphic if both can converted other in "lossless" fashion pair of inverse functions. in case, either e a
, eithert e identity a
isomorphic because following 2 functions inverses:
toeither :: exceptt e identity -> either e toeither ma = runidentity (runexceptt ma) toexceptt :: either e -> exceptt e identity toexceptt (left e) = throwerror e toexceptt (right a) = return
so going informal remarks above, tells 2 types "essentially same." , meat inverse functions add prove that:
- if have piece of code uses either type, can refactor use other , code produce same results , behavior;
- if have 2 separate libraries, 1 of them uses first type , other uses second, can bridge between them using isomorphism functions , fine.
so comes down in programming there many different ways of doing exactly same thing. in case, exceptt
more general version of either
, when plug in identity
base monad works same either
does. prefer use either
in case because don't have boilerplate, still find ourselves in situation exceptt e identity a
, knowing isomorphism helps understand it's not different either e a
.
here's way analyze this. exceptt
type defined this:
newtype exceptt e m = exceptt { runexceptt :: m (either e a) }
in haskell, newtype
definition isomorphism (the exceptt
constructor , runexceptt
function inverses), in case means following 2 types isomorphic:
exceptt e m ~ m (either e a)
which means these 2 isomorphic well:
exceptt e identity ~ identity (either e a)
but identity
defined newtype
:
newtype identity = identity { runidentity :: }
which means isomorphism holds well:
identity ~
and therefore these ones:
identity (either e a) ~ either e exceptt e identity ~ either e
so when library transparently defines type newtype
, pays notice fact. (and that's why library documentation in haskell tells whether data types exported constructors data
or newtype
definition—knowing it's newtype
big deal.)
another benefit of looking @ in terms of isomorphisms helps understand lot of standard haskell libraries better. said above, newtype
definition of exceptt
, following isomorphism holds
exceptt e m ~ m (either e a)
when working monadic type of form m a
, call m
"monad" , a
"result type". looking @ through lens, then:
- in
m (either e a)
,m
monad ,either e a
result type; - in
exceptt e m a
,exceptt e m
monad ,a
result type.
so exceptt
monad transformer isomorphism allows "flip perspective" on computations of type m (either e a)
treat a
result type instead of either e a
. "changing meaning" of monad operations mean in m
accounts "perspective flip" in question.
Comments
Post a Comment