Возможно ли скопировать сообщения об ошибках в Monad ErrorT? Я хотел бы накопить больше одной ошибки.Накопление ошибок с использованием ErrorT
1
A
ответ
4
Вы можете использовать Errors
Аппликативные из Control.Applicative.Lift
из трансформаторов:
ghci> import Control.Applicative
ghci> import Control.Applicative.Lift
ghci> failure ['a'] *> pure() <* failure ['b']
Other (Constant "ab")
возвращает список ошибок, если таковые имеются, или успешный результат.
Этот тип обычно известен как «Валидация». Есть other implementations из имеющихся в Hackage. Одно из возможных улучшений заключается в том, чтобы уменьшить потребность в контейнере отказов Monoid
, что позволяет также Semigroup
с.
Обратите внимание, что тип Errors
не является Monad
. Но вы можете комбинировать его с другими Applicative
с помощью Data.Functor.Compose
.
MonadPlus
экземпляра для ExceptT
имеет связанное, но не идентичное поведение: он возвращает первый успех, если есть, или список ошибок:
ghci> throwE ['a'] `mplus` return() `mplus` throwE ['b'] :: ExceptT [Char] Identity()
ExceptT (Identity (Right()))
ghci> throwE ['a'] `mplus` throwE ['b'] :: ExceptT [Char] Identity()
ExceptT (Identity (Left "ab"))
'Either' /' ExceptT'/'ErrorT' по своей сути предназначены для короткого замыкания, поэтому ответ« нет ». Если вы хотите скопировать несколько ошибок, вы должны использовать другой трансформатор monad/monad, в данном случае, вероятно, 'WriterT'. –
Трудно ли заменить ErrorT на WriterT? В этот момент у меня есть «башня: из монады (StateT, ErrorT, IO) –
Это не сложно в том смысле, что это механически сложно, но это может быть сложно в том смысле, что' ErrorT' и 'WriterT' имеют чрезвычайно разную семантику. Весь смысл «ErrorT» заключается в том, что он позволяет с ошибками вычислять. Если вы хотите скопировать более одной ошибки, значит, вы, вероятно, хотите, чтобы вычисления продолжали идти. Подумайте, какие последствия для вашего кода - можете ли вы действительно продолжать идти после сбоя? Если ответ «иногда», вам может понадобиться смесь 'WriterT' и' ExceptT' ('ErrorT' устарел, кстати, вместо этого используйте' ExceptT'). –