我有一个可以从Haskell中的多个参数创建的类,该类需要对这些参数进行一些复杂的验证。目前我有类似的东西
makeAThingExcept :: String -> String -> ... String -> Except ThingError AThing
makeAThingExcept s1 s2 ... = do
unless (s1CheckPasses s1) (throwError (BadS1 s1))
...
data ThingError = BadS1 String ...
instance Show ThingError where
show (BadS1 s) = "Bad S1: " ++ s
makeAThing :: String -> String -> ... String -> AThing
makeAThing s1 s2 ... = case runExcept (makeAThingExcept s1 s2 ...) of
Right thing -> thing
Left err -> error (show err)
通过使用比String
更具体的类型作为makeAThingExcept
的参数,是否还有其他更好的方法来实现此目的,是否有理由更喜欢Except
胜过{{1}在这种情况下? Either
与Except
的功能和习语之间有什么区别?
答案 0 :(得分:3)
不同的是在实例Alternative
。正如我猜想的那样,“基本”包不会为Either
导出任何内容,因为作者不想对任何值引入偏见,这本身就是因为Either
应该是一般的总和型,不只是代表可能的错误。但是the "transformers" package does provide an orphan instance会将其绑定到the Error
class:
Error e => Alternative (Either e)
但是,社区从未接受过该类型类或孤立实例,因此现在不推荐使用它。哎呀,您可以将其视为Either
仍然没有Alternative
的实例。
Except
类型确实具有一个非孤立实例,该实例甚至不将用户绑定到任何虚构类,而是使用Monoid
:
(Functor m, Monad m, Monoid e) => Alternative (ExceptT e m)
答案 1 :(得分:1)
如注释中所述,很容易在Either
和Either
之间进行转换。运行时表示形式也相同。
我总是选择使用Except
。它在图书馆中无处不在。我很少看到Except
。
Reader SomeType (Either e a)
是ExceptT的特例,您会在库中看到它们。如果您发现自己使用IO (Either e a)
或Monad m => m (Either e a)
或ExceptT
编写了很多函数,那么您可能要考虑使用Either
。最好不要担心,直到{{1}}都更容易使用。