Haskell中Either和Except在用法上有什么区别?
What are the difference in usage between Either and Except in Haskell?
我有一个 class 可以从 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
而不是 Either
在这种情况下? Except
与 Either
的功能和习语之间有什么区别?
如评论中所述,Except
和 Either
之间的转换很容易。运行时表示是相同的,甚至。
我会一直选择使用 Either
。它在图书馆无处不在。我很少看到 Except
。
Except
是 ExceptT 的特例,您 将 在图书馆中看到。如果你发现自己用 Reader SomeType (Either e a)
或 IO (Either e a)
或 Monad m => m (Either e a)
编写了很多函数,那么你可能要考虑 ExceptT
。在那之前不要担心 - Either
更容易使用,直到它不是。
区别在于 Alternative
的实例。 "base" 包不会为 Either
导出任何内容,据我所知,因为作者不想引入对任何值的偏见,这本身是因为 Either
应该是是一般的求和类型,表示出错的可能性只是特例。然而 the "transformers" package does provide an orphan instance, which binds it to the Error
class:
Error e => Alternative (Either e)
然而,社区从未接受过类型类或孤儿实例,这就是它现在被弃用的原因。 IOW 你可以看看它好像 Either
仍然没有 Alternative
.
的实例
Except
类型确实有一个非孤立实例,它甚至不将用户绑定到任何虚构的 类,而是 Monoid
:
(Monad m, Monoid e) => Alternative (ExceptT e m)
还值得注意的是,对于处理验证和累积所有错误的情况,the Validation
abstraction 更合适。但是有一个权衡:它不能是一个 monad,但它是一个选择性的(在 applicative 和 monad 之间)和一个替代。
我有一个 class 可以从 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
而不是 Either
在这种情况下? Except
与 Either
的功能和习语之间有什么区别?
如评论中所述,Except
和 Either
之间的转换很容易。运行时表示是相同的,甚至。
我会一直选择使用 Either
。它在图书馆无处不在。我很少看到 Except
。
Except
是 ExceptT 的特例,您 将 在图书馆中看到。如果你发现自己用 Reader SomeType (Either e a)
或 IO (Either e a)
或 Monad m => m (Either e a)
编写了很多函数,那么你可能要考虑 ExceptT
。在那之前不要担心 - Either
更容易使用,直到它不是。
区别在于 Alternative
的实例。 "base" 包不会为 Either
导出任何内容,据我所知,因为作者不想引入对任何值的偏见,这本身是因为 Either
应该是是一般的求和类型,表示出错的可能性只是特例。然而 the "transformers" package does provide an orphan instance, which binds it to the Error
class:
Error e => Alternative (Either e)
然而,社区从未接受过类型类或孤儿实例,这就是它现在被弃用的原因。 IOW 你可以看看它好像 Either
仍然没有 Alternative
.
Except
类型确实有一个非孤立实例,它甚至不将用户绑定到任何虚构的 类,而是 Monoid
:
(Monad m, Monoid e) => Alternative (ExceptT e m)
还值得注意的是,对于处理验证和累积所有错误的情况,the Validation
abstraction 更合适。但是有一个权衡:它不能是一个 monad,但它是一个选择性的(在 applicative 和 monad 之间)和一个替代。