Невозможно восстановить ошибки в Conduit

Я пытаюсь понять, как ловить ошибки, возникающие в каналах. Я полагал, что, применив catchC к каналу, я смогу создать новый канал, который будет работать повторно в случае отказа.

В приведенном ниже примере у нас есть источник, который, в зависимости от логического значения, выдает пользовательское фиктивное исключение. Первоначально значение этого логического значения приводит к возникновению этого исключения, однако обработчик внутри catchC создает новый канал, который должен демонстрировать противоположное поведение (выдавая числа от 1 до 10).

{-# LANGUAGE DeriveDataTypeable #-}

module Main where

import Data.Conduit
import qualified Data.Conduit.List as CL
import Control.Monad.IO.Class
import Control.Exception
import Data.Typeable

data MyException = MyException String
    deriving (Show, Typeable)

instance Exception MyException where

listAsStream :: Bool -> Source IO Int
listAsStream val =  if val then CL.sourceList [1..10] else throw $ MyException "Value"

conduitWhatever :: Sink Int IO ()
conduitWhatever = awaitForever $ liftIO . print

main :: IO ()
main = catchC (listAsStream False) handler $$ conduitWhatever

handler :: MyException -> Source IO Int
handler _= catchC (listAsStream True) handler

Я почти уверен, что неправильно понял, как работает catchC. Может ли кто-нибудь объяснить мне, что я делаю неправильно?

Большое спасибо!


person rubioz    schedule 21.01.2015    source источник


Ответы (1)


Вы правильно используете catchC; проблема заключается в использовании throw, которое вводит неточное исключение вместо правильного исключения IO. Если вы вместо этого используете:

liftIO $ throwIO $ MyException "Value"

ваша программа работает так, как ожидалось.

person Michael Snoyman    schedule 21.01.2015