[英]What purpose does the complexity of `Except` serve in Haskell?
我理解 (我認為)在Haskell中Either
和Except
之間存在密切關系,並且很容易從一個轉換為另一個。 但是我對在Haskell中處理錯誤的最佳實踐以及在什么情況和情況下我會選擇其中一個而感到困惑。 例如,在Control.Monad.Except
提供的示例中,在定義中使用了Either
type LengthMonad = Either LengthError
所以calculateLength "abc"
是
Right 3
相反,如果要定義
type LengthMonad = Except LengthError
然后calculateLength "abc"
將是
ExceptT (Identity (Right 3))
我很困惑這會起什么作用,何時需要它。 為什么從calculateLength
返回的所有內容總是具有Identity
; 為什么不只是SomeExceptionType (Right 3)
甚至SomeSuccessType 3
?
當談到像這樣的概念時,我是一個Haskell的初學者,所以當我希望后者超過前者時,我會非常感激,特別是為什么它(顯然對我來說)很復雜。 例如,使用Except
calculateLength
版本的函數的調用者可以做什么,他們不能(或至少不能那么容易)使用Either
版本?
將Either
用於正常成功/錯誤 API。 它在基礎庫中定義,因此不會將其他依賴項推送到使用者身上。 此外,這是最基本的Haskell類型之一,因此'每個人'都了解它的工作原理。
如果您特別需要將Either
與另一個monad(例如IO
)組合,則僅使用ExceptT
。 此類型在變換器庫中定義,因此會對消費者產生額外的依賴性。 另外,monad變換器是Haskell的一個更高級的功能,所以你不能指望每個人都能理解如何使用它。
做出這些決定時,我並不在身邊,但似乎有各種歷史原因引起混淆 。 Haskell是一種古老的語言(比Java早!),所以即使已經努力簡化它並糾正舊的錯誤,一些仍然存在。 據我所知, Either
/ ExceptT
混淆是其中一種情況。
我猜測 Either
比monad變換器的概念要老,所以我想在早期的Haskell歷史中將類型Either
引入基礎庫。
Maybe
似乎也是如此。
其他monad,例如Reader和State似乎已經與他們的monad變換器一起被引入(或至少'retconned')。 例如, Reader
只是ReaderT
一個特例 ,其中'其他' Monad
是Identity
:
type Reader r = ReaderT r Identity
StateT
:
type State s = StateT s Identity
這是變形金剛庫中定義的許多monad的一般模式。 ExceptT
只是遵循模式,將Except
定義為ExceptT
。
這種模式有例外。 例如, MaybeT
沒有將Maybe
定義為特例。 我再次相信這是出於歷史原因; Maybe
很久很久才有人開始研究變形金剛圖書館。
關於Either
的故事似乎更令人費解。 據我所知, 有 ,原來,一個EitherT
單子轉換,但顯然(我忘了細節)有一些錯誤的方式,它的表現(它可能打破了一些法律),因此,它與另一變壓器更換叫做ErrorT
,后來又證明是錯的。 我想,第三次是魅力,所以引入了ExceptT
。
Control.Monad.Trans.Except
模塊遵循大多數其他monad變換器的模式,通過使用類型別名定義'無效'特殊情況:
type Except e = ExceptT e Identity
我想這樣做是因為它可以,但它可能是不幸的,因為它令人困惑。 絕對現有技術表明monad變換器不必遵循該模式(例如MaybeT
),所以我認為如果模塊沒有這樣做會更好,但確實如此,那就是我們所處的位置。
我基本上會忽略Except
類型並使用Either
代替,但如果需要變換器則使用ExceptT
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.