2015-07-04 38 views
9

現在Control.Monad.Error不推薦使用,並且Control.Monad.Except統治至高無上,很多網上來源沒有追上,並且仍然展示如何使用Error的例子。適應錯誤除

那麼我將如何去使用Except轉向

instance Error MyError where 
    noMsg = ... 
    strMsg = ... 

到的東西。只是Except更換ErrorExcept沒有工作,預計額外的類型參數

據我所知,在Except不存在這些確切的方法,有什麼辦法呢?

回答

9

簡短的回答是:通過什麼替換Error所有,由ExceptT更換ErrorT,事情應該繼續,只要工作,因爲你不使用Error小號方法,fail(現在有不同的定義),或失敗模式符合do表示法。

Control.Monad.Error系統和新系統Control.Monad.Except之間的本質區別是,新的操作系統對錯誤/異常類型沒有類限制。

它被發現能夠根據多態使用任何錯誤/異常類型,比自定義字符串錯誤消息轉換有點冒險的能力更有用。

因此,類Error已經完全消失。

作爲副作用,的fail現在已從底層monad中解除。這也改變了do表示法中失敗模式的影響。

舊的定義是:

fail msg = ErrorT $ return (Left (strMsg msg)) 

我認爲這是相當於

fail msg = throwError (strMsg msg) 

如果您仍需要這種行爲,你可以改用

throwError yourIntendedErrorValue 

throwE作品相反,如果您使用transformers(即Control.Monad.Trans.Except),而不是mtl

do模式匹配失敗將政策適用於

do 
    Just x <- myErrorTAction 
    ... 

時的動作實際上返回Nothing。這比較尷尬,但你可以有一個明確的case比賽(基本上脫糖吧)替換爲:

do 
    y <- myErrorTAction 
    case y of 
     Nothing -> throwE ... 
     Just x -> do 
      ... 

@DanielWagner提出以下建議,以避免額外的縮進:

do 
    x <- myErrorTAction >>= maybe (throwError ...) return 
    ... 

Error去除也消除了命名不一致的需要Control.Monad.Error有:大多數變壓器遵循的規則是SomethingT是變壓器的名稱,而SomethingSomethingT ... Identity的類型別名。舊的ErrorT打破了,因爲Error類被用於完全不同的東西。

在新系統中,Except e = ExceptT e Identity與其他變壓器一樣。

+0

你說「失敗」現在有不同的作用,你能否提供一個例子,以及如何編寫等效代碼? –

+0

@ElectricCoffee我擴大了那一點。 –

+1

@ØrjanJohansen偶爾使用的另一種模式:'do {y < - myErrorTAction >> = maybe(throwError ...)return; ''。避免必須添加縮進級別,並且可以適應其他模式匹配;例如'do {y_ < - myErrorTAction; y < - case {沒有 - > throwError ...;只是v - >返回v}; ...}'它添加了一個縮進層,但只是暫時的(即如果你想做兩個模式匹配就不需要嵌套縮進)。 –