Haskell MonadError不应该再使用了?
我有一个关于Haskell MonadError不应该再使用了?,haskell,Haskell,我有一个关于MonadError的问题,即与其使用MonadError,不如使用?MonadError和除了之外都不是相互排斥的。它们是不同种类的东西 MonadError是一个类型类(即“接口”),它定义了某些操作(throwError和catchError),这些操作可以由不同的monad实现。如果函数的类型签名需要MonadError,则表示“我将在任何monad中工作,只要它实现MonadError,因为我使用其中定义的操作”,例如: f :: MonadError MyErrorTyp
MonadError
的问题,即与其使用MonadError
,不如使用?MonadError
和除了
之外都不是相互排斥的。它们是不同种类的东西
MonadError
是一个类型类(即“接口”),它定义了某些操作(throwError
和catchError
),这些操作可以由不同的monad实现。如果函数的类型签名需要MonadError
,则表示“我将在任何monad中工作,只要它实现MonadError
,因为我使用其中定义的操作”,例如:
f :: MonadError MyErrorType m => Int -> m String
另一方面,除了,是一个具有特定底层实现的特定monad。这个特定的monad恰好实现了来自MonadError
的操作,这意味着需要MonadError
的任何函数都可以在中使用,除了
:
runExcept $ f 42 -- using the definition of `f` above
您还可以声明您的函数专门用于除之外的,而不是“在实现MonadError的任何东西中”:
除了如f可以:
runExcept $ g 42
但它不能用于实现MonadError
的其他monad中
这样做的实际后果是,如果您正在编写一些本地的、小型的、简单的程序,那么除了,您可以在中编写所有函数,但是如果您正在编写一个包含大量模块的更大系统,或者更好的是一个可重用的库,那么最好在MonadError
中编写函数,因为这样你的消费者在使用你的图书馆时会有更多的自由。在OO世界中,这个想法被称为“”
这样做的一个可能缺点是代码可能(并非总是)性能较差,因为编译器可能无法在不知道所有内容的最终类型的情况下进行足够的内联。然而,实际上,在大多数应用程序中,性能损失是微不足道的。通常的准则是:先测量,然后优化。你为什么这么认为?这是两个完全不同的东西,我倾向于相信它们在不同的情况下是有用的。你能解释一下情况吗,我什么时候必须使用什么?
runExcept $ g 42