在ExceptT中包装管道

时间:2016-06-18 01:44:26

标签: haskell conduit

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 个答案:

答案 0 :(得分:1)

要记住的有用签名是:

options

并考虑到这一点,此代码类型检查:

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的版本:

Sink