Аннотация
Используйте Either
для нормальных успех / ошибка API.Он определен в библиотеке base , поэтому он не распространяет другие зависимости на потребителя.Кроме того, это один из самых базовых типов Haskell, поэтому «все» понимают, как он работает.
Используйте ExceptT
только в том случае, если вам нужно специально объединить Either
с другой монадой (например, например,IO
).Этот тип определен в библиотеке transformers , поэтому он требует дополнительной зависимости от потребителей.Кроме того, монадные преобразователи - это более продвинутая функция Haskell, поэтому нельзя ожидать, что все поймут, как ее использовать.
Предположение о причинах
Меня не было рядом, когда принимались эти решениясделал, но кажется, что существуют разные исторические причины для путаницы .Haskell - это старый язык (более старый, чем Java!), Поэтому, хотя были предприняты попытки упростить его и исправить старые ошибки, некоторые все еще остаются.Насколько я могу судить, путаница Either
/ ExceptT
является одной из таких ситуаций.
Я предполагаю , что Either
старше концепции монадных трансформаторовпоэтому я представляю, что тип Either
был введен в библиотеку base в начале истории Haskell.
То же самое можно сказать и о Maybe
.
Другие монады, например, Reader и State , кажется, были введены (или, по крайней мере, "повторно") вместе с их монадными трансформаторами.Например, Reader
это просто особый случай из ReaderT
, где «другое» Monad
равно Identity
:
type Reader r = ReaderT r Identity
То же самое относится к StateT
:
type State s = StateT s Identity
Это общая схема для многих монад, определенных в библиотеке transformers .ExceptT
просто следует шаблону, определяя Except
как особый случай ExceptT
.
Есть исключения из этого шаблона.Например, MaybeT
не определяет Maybe
как особый случай.Опять же, я считаю, что это по историческим причинам;Maybe
, вероятно, существовал задолго до того, как кто-то начал работать над библиотекой transformers .
История с Either
кажется еще более запутанной.Насколько я могу судить, там был , первоначально, EitherT
монадный трансформатор, но, очевидно, (я забыл детали) было что-то не так с его поведением (возможно, оно нарушало некоторые законы)Таким образом, он был заменен другим трансформатором с именем ErrorT
, который снова оказался неправильным.В третий раз, я полагаю, это очарование, поэтому было введено ExceptT
.
Модуль Control.Monad.Trans.Except
следует шаблону большинства других монадных преобразователей, определяя «неэффективный» особый случай с использованием псевдонима типа:
type Except e = ExceptT e Identity
Я полагаю, что это так, потому что это возможно, но это может быть неудачно, потому что это сбивает с толку.Существует определенный уровень техники, который предполагает, что монадный преобразователь не должен следовать этому шаблону (например, MaybeT
), поэтому я думаю, что было бы лучше, если бы модуль не сделал этого, но это происходит, и именно здесьявляются.
Я бы по существу проигнорировал тип Except
и использовал бы вместо него Either
, но использовал бы ExceptT
, если требуется трансформатор.