Предположим, что ваш сегмент кабелепровода раковины — C.mapM_ BS.putStrLn
.
Первый шаг — развернуть значение ExceptT и сравнить его с сегментом приемника:
runExceptT sourceMsg :: ConduitM () ByteString IO (Either Err ())
C.mapM_ BS.putStrLn :: ConduitM ByteString a IO ()
Когда вы используете операторы объединения Conduit, вы должны выбрать, какой сегмент будет возвращать значение объединенного выражения. Два основных варианта:
a =$= b -- b returns the value
a `fuseUpstream` b -- a returns the value
Поскольку мы хотим увидеть значение Either Err ()
, мы будем использовать fuseUpstream
:
let f = (runExceptT sourceMsg) `fuseUpstream` (C.mapM_ BS.putStrLn)
:: ConduitM () c IO (Either Err ())
(Еще одно требование для объединения двух сегментов состоит в том, что сегмент, не возвращающий значение, должен возвращать ()
. В нашем случае это уже удовлетворяет C.mapM_ ...
, но в целом это нужно проверить. Сегмент всегда может быть изменен, чтобы возвращать ()
, сопоставляя его с const ()
)
Следующим шагом является запуск объединенных сегментов для получения действия ввода-вывода:
runConduit f :: IO (Either Err ())
и теперь мы можем сказать, получили мы ошибку или нет. Полное решение:
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad.Trans.Except
import Data.Conduit as C
import Data.Conduit.List as C
import qualified Data.ByteString.Char8 as BS
import Data.ByteString (ByteString)
import Control.Monad
type Err = (Int, String)
sourceMsg :: ExceptT Err (ConduitM () ByteString IO) ()
sourceMsg = undefined
runSource = do
do r <- runConduit $ (runExceptT sourceMsg) `fuseUpstream` (C.mapM_ BS.putStrLn)
case r of
Left _ -> putStrLn "error"
Right _ -> putStrLn "no error"
person
ErikR
schedule
18.06.2016