2016-06-18 3 views
1

Что такое хороший способ обертывания трубопровода в ExceptT? Подход должен прекратить обработку при возникновении ошибки и извлечь сообщение об ошибке. Вот это игрушка код без обработки ошибок - он просто молча останавливается:Упаковочный трубопровод в 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() 

Как мы можем изменить тип подписи sink к чему-то, как показано ниже?

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

В случае Left, это будет приятно вырваться из трубопровода, и возвращает сообщение об ошибке в верхней части. Я читал это blog post, но еще не понял его достаточно хорошо, чтобы применить его к кабелепроводу (который также имеет сложную подпись типа). Я хотел бы применить предлагаемый подход here к кабелепроводу - кажется, EitherT, предложенный в подходе, теперь включен в ExceptT.

ответ

1

Полезным подпись помнить:

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

и с этим в виду, этот тип кода проверки:

{-# 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() 

Это не совсем раковина, но он должен показать, как заниматься вещами.

типирование на линии (***) выглядит следующим образом:

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() 

Таким образом, использование return здесь устанавливает вещи таким образом, мы можем применить ExceptT конструктор.

Затем, когда вы вызываете bind на значении ExceptT ..., вы вызываете код ошибки , который предоставляет ExceptT. Таким образом, если inp был равен Left, ошибка будет поднята.

Update

Вот версия с 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

Спасибо. Я знаком с exceptT, но до сих пор не могу понять, как иметь подпись, такую ​​как «ExceptT Err» (Consumer ByteString m())(). Не уверен, что это хороший способ пойти либо потому, что я пытаюсь обработать ошибки на вершине уровня конвейера - что-то вроде этого ' $$ ', который, если в состоянии 'Left' в любой точке должен остановить и вернуть ошибку «Left». В случае 'Pipes', это' ExceptT e ​​(Pipe a b m) r', как указано в сообщении, которое я связал в своем вопросе. – Sal

+0

Отвечено обновлено с помощью 'Sink'. На самом деле я не думаю, что вы можете создать «ExceptT Err (Consumer ...)», потому что потребитель универсально квалифицирован по одному из своих параметров типа. 'Pipe' не определен так - он ближе к' Sink'. Поэтому я думаю, что «ExceptT ... Sink ...» - это то, что вы ищете – ErikR

+0

Да, я понял то же самое. Большое спасибо за помощь. – Sal

Смежные вопросы