2012-07-09 33 views
4

我目前正在爲我的一個小項目編寫一些pipe-core/attoparsec管道。我希望每個解析器都提供一個管道,等待輸入到解析器的ByteString並生成任何解析的值(重新啓動解析器)。如果沒有錯誤處理,它會因此有一個像使用管道(-core)進行錯誤處理的方法是什麼?

parserP :: Monad m => Parser a -> Pipe ByteString a m r 

現在,我不確定如何處理解析錯誤。我現在的想法是:

  • 的錯誤添加到返回類型
  • 要求單子提供的錯誤處理機制(即Either ParseError r而不僅僅是r返回一個值)(即要求單子的管被接管實現MonadError
  • 力單子通過接管ErrorT e m a所述管爲任何單子m
  • 將參數添加到提供一個錯誤機構,讓用戶指定b ehaviour(像(ParseError -> P.Pipe ByteString a m r),和簡單地結合到如此提供管在解析錯誤的情況下)

第一溶液似乎是錯誤的,如使用用於錯誤處理的管的返回類型似乎是相當一劈。首先,它使用管道醜陋構成組合,似乎或多或少被最終解決方案所包含(除了可能失去使下游管道能夠通過使用tryAwait從錯誤中恢復並停止等待值的能力?)。

第二種解決方案似乎是錯誤的,儘管我無法完全理解爲什麼。可能是因爲它可能(可能?)也需要將一個參數轉換成ParseError成爲Monad所具有的任何錯誤類型(除非我們希望要求monad實現MonadError ParseError,這看起來會導致很多記錄)。最後,我似乎無法記住看到MonadError這麼多,這表明使用它有一些問題。

第三種解決方案適用於我的情況,因爲管道將是用戶指定monad(IO)管道的一部分,不應該關心解析錯誤(它會將網絡數據解析爲格式屈服於用戶指定的類型)。但它似乎並不是那麼優雅,並且會再次(可能?)導致大量的書籍保留,一旦用於任何其他環境。

我還沒有真正想過最終的解決方案,但似乎有些複雜。

對於關於這個特殊情況的任何想法,我將不勝感激(如果我的方式不明確,我不會感到驚訝)以及任何(或多或少相關的)關於錯誤討論的參考在管道(核心)/管道/ interatee等處理

編輯: 另一種可能性是採取一次性動作(而不是一個完整的管道),儘管我不太確定它是否可能只是概括,專門化或甚至相當於第四個。

+0

我會注意到建議3(使用'ErrorT e m a')完全被我個人最喜歡的建議2(使用'MonadError')包含。但我不確定如何對這個問題作出客觀的回答。 – 2012-07-10 08:37:58

+2

我通過電子郵件發送了Gabriel通知他,因爲他是[管道](http://hackage.haskell.org/package/pipes)和[錯誤](http://hackage.haskell)的作者。 org/package/errors)包;據推測他一直在思考這兩件事情,可能在一起。 – 2012-07-10 10:14:36

+0

@DanielWagner我同意它似乎是上述最好的解決方案。事情是,我總是引入額外的類型類;特別是對於任何不僅僅是運營商超載而言。 – 2012-07-10 10:57:32

回答

7

如果可以,我想我可以通過描述這樣的選擇來幫助組織大家的想法。您:

  1. Pipe一個EitherT/ErrorT內:

    EitherT E(管ABM)R

  2. Pipe外部的EitherT/ErrorT的:

    管AB( EitherT em)r

你想要的前一種方法,它也有很好的屬性,你可以使它成爲MonadError的一個實例(如果那是你的東西)。

爲了理解這兩種方法之間的差異,第二種方法在整個管道級別拋出錯誤。第一個允許在單個管道的粒度上進行錯誤處理並正確處理組成的管道。

現在有些代碼。我將使用EitherT如果你不介意,因爲我更舒服:

import Control.Error 
import Control.Pipe 

type PipeE e a b m r = EitherT e (Pipe a b m) r 

runPipeE = runPipe . runEitherT 

p1 <?< p2 = EitherT (runEitherT p1 <+< runEitherT p2) 

然後,只需一個PipeE你的心臟的內容中使用catchT和throwT。

這種方法還有另外一個好處,那就是你可以有選擇地將它應用到管線的某些部分,但是你必須負責在與其他管道合併之前處理潛在的異常值。您可以使用這種靈活性爲流水線的不同階段使用不同類型的異常值,或者根本不使用它來執行不會失敗的階段,並避免錯誤檢查這些階段的開銷。

+2

一個很好的減少/簡化問題,以及在這個特殊情況下應用什麼方法的好建議,完美! – 2012-07-10 16:54:12

相關問題