2016-06-18 2 views
1

Was ist ein guter Weg, um eine Leitung in ExceptT zu wickeln? Der Ansatz sollte die Verarbeitung bei einem Fehler stoppen und die Fehlermeldung extrahieren. Hier ist ein Spielzeug-Code ohne Fehlerbehandlung - es ist nur still hält:Einwickelschlauch in ExceptT

import Data.Conduit as C 
import Data.ByteString as BS 
import Control.Monad 
import Control.Monad.IO.Class 
import Data.Text as T 

-- just a dummy processing to simulate errors 
process :: BS.ByteString -> Either (Int,T.Text) BS.ByteString 
process inp = if (BS.null inp) then Left $ (1,"Empty input") else Right inp 

-- silent processing - stops on error but doesn't tell us what it is 
sink :: MonadIO m => Consumer BS.ByteString m() 
sink = do 
     bs <- await 
     case bs of 
     Just val -> do 
      let msg = process val 
      case msg of 
       Left _ -> return() 
       Right x -> (liftIO $ return x) >> sink 
     Nothing -> return() 

Wie könnten wir die Art Signatur von sink so etwas wie unten ändern?

sink :: MonadIO m => ExceptT e m (Consumer BS.ByteString m()) 

Bei Left, wird es schön, aus der Pipeline zu brechen, und gibt die Fehlermeldung nach oben. Ich lese dies blog post, aber habe es noch nicht gut genug verstanden, um es auf Conduit (die auch komplizierte Signatur hat) anzuwenden. Ich möchte den vorgeschlagenen Ansatz here auf Conduit anwenden - es scheint EitherT vorgeschlagen in der Ansatz wurde nun von ExceptT subsummiert.

Antwort

1

Eine nützliche Unterschrift zu erinnern ist:

ExceptT :: m (Either e b) -> ExceptT e m b 

und mit dem im Verstand, diese Art Code überprüft:

{-# LANGUAGE OverloadedStrings #-} 

import Control.Monad.Trans.Class 
import Control.Monad.Trans.Except 

import Data.Conduit as C 
import Data.ByteString.Char8 as BS 
import Control.Monad 
import Control.Monad.IO.Class 
import Data.Text as T 

-- just a dummy processing to simulate errors 
process :: BS.ByteString -> Either (Int,T.Text) BS.ByteString 
process inp = if (BS.null inp) then Left $ (1,"Empty input") else Right inp 

type Err = (Int,T.Text) 

sink' :: MonadIO m => ExceptT Err (ConduitM ByteString Int m)() 
sink' = do bs <- lift await 
      case bs of 
       Just inp -> do 
       msg <- ExceptT (return $ process inp) -- *** 
       lift $ yield (BS.length msg) 
       liftIO $ BS.putStrLn msg 
       sink' 
       Nothing -> return() 

Das ist nicht gerade ein Waschbecken, aber es sollte zeigen, wie man Dinge tun.

Die Eingabe auf Linie (***) geht so:

process inp    :: Either Err ByteString 
          -- (a pure value) 
return (process inp) :: m (Either Err ByteString) 
          -- here m = ConduitM ByteString Int mIO 
ExceptT (...)   :: ExceptT Err m() 

So ist die Verwendung von return hier setzt die Dinge so können wir den ExceptT Konstruktor gelten.

Wenn Sie dann Bindung auf einen ExceptT ...-Wert aufrufen, lösen Sie den Fehlerprüfcode aus, der von ExceptT bereitgestellt wird. Wenn also inp ein Left ist, wird ein Fehler ausgelöst.

aktualisieren

Hier ist eine Version mit Sink:

sink' :: MonadIO m => ExceptT Err (Sink ByteString m)() 
sink' = do bs <- lift await 
      case bs of 
       Just inp -> do 
       msg <- ExceptT (return $ process inp) 
       liftIO $ BS.putStrLn msg 
       sink' 
       Nothing -> return() 
+0

Danke. Ich bin mit exceptT vertraut, kann aber immer noch nicht herausfinden, wie man eine Signatur wie 'ExceptT Err (Consumer ByteString m())()' hat. Nicht sicher, ob das ein guter Weg ist, entweder weil ich versuche, die Fehlerverarbeitung oben auf der Pipeline-Ebene zu machen - etwas wie dieses " $$ ", das zu irgendeinem Zeitpunkt im "linken" Zustand ist sollte aufhören und 'Left' Fehler zurückgeben. Im Falle von 'Pipes' ist es' ExceptT e ​​(Pipe a b m) r ', wie in dem Post erwähnt, den ich in meiner Frage verlinkt habe. – Sal

+0

Antwort aktualisiert mit 'Sink'. Eigentlich glaube ich nicht, dass Sie "ExceptT Err (Consumer ...)" erstellen können, da Consumer über einen seiner Typparameter universell qualifiziert ist. 'Pipe' ist nicht so definiert - es ist näher an' Sink'. Also ich denke 'AusgenommenT ... Sink ...' ist was du suchst – ErikR

+0

Ja, ich dachte das gleiche. Vielen Dank für Ihre Hilfe. – Sal