Использование GADT для обработки исключений

вот моя проблема

Я использую Control.Exception.catch для обработки исключений следующего типа: (выбрано из Hoogle)

catchSource
:: Exception e   
=> IO a 
The computation to run
-> (e -> IO a)  
Handler to invoke if an exception is raised
-> IO a  

Вот конструктор, который я передам своей функции-обработчику.

> data JobException = PreProcessFail
>                   | JobFail
>                   | ChartFail
>                       deriving (Show, Typeable)

> instance Control.Exception JobException

Вот функция Handler, как она есть сейчас:

> exceptionHandler :: JobException -> IO ()
> exceptionHandler exception = do
>    writeFile "testException.txt" ("caught exception " ++ show exception )

Я собираюсь использовать это, чтобы вести журнал. Информация, которую мне нужно зарегистрировать, будет в записи типа JobState.

> type JobState = MVar ProcessConfig

> data ProcessConfig = PConfig { model :: ServerModel
>                              , ipAddress :: String
>                              , cookie :: Cookie
>                              } deriving Show

Итак, поскольку мне нужен обработчик, который принудительно имеет тип, упомянутый выше, и мне нужен JobState, я подумал, что ответ будет заключаться в том, чтобы переписать JobException, чтобы скрыть внутри него JobState. Кажется, это работа для GADT! Я не уверен, это новая территория.

Я прав? Могу ли я решить эту проблему с помощью GADT? Может ли кто-нибудь подсказать, как начать его строить? Учебники, которые я читал, предполагают, что вы пытаетесь решить более сложную проблему, чем та, что есть у меня.

Если я ошибаюсь, может ли кто-нибудь указать мне правильное направление?

обновление: я узнал о динамических типах из 1 и нашел вскоре после этого Data.Dynamic. Становится теплее?

Развлечение с фантомными типами


person Michael Litchard    schedule 14.09.2011    source источник
comment
Почему вы не можете просто включить JobState в исключение? Почему ГАДТ?   -  person augustss    schedule 15.09.2011
comment
То, как я сейчас настроил JobException, заключается в том, что функции, выбрасывающие исключение, будут выдавать только PreProcessFail, JobFail или ChartFail. Мне нужно каким-то образом включить, например, JobFail и JobState. Трудно представить, как это сделать со стандартными типами. Прочитав Fun With Phantom Types, похоже, я хочу пойти по этому пути. Не могли бы вы продемонстрировать мне, что вы имеете в виду?   -  person Michael Litchard    schedule 15.09.2011
comment
Когда я пытаюсь включить JobState в JobException, я получаю жалобы на то, что экземпляр Show for JobState не существует. Я понятия не имею, как написать этот экземпляр, учитывая, что JobState является MVar.   -  person Michael Litchard    schedule 15.09.2011


Ответы (1)


Экземпляр исключений Show в основном используется, когда вы не обрабатываете исключение самостоятельно и оно выводится где-то еще в вашей программе (например, на верхнем уровне). Поскольку вы перехватываете исключения с помощью специального обработчика, вы должны иметь возможность просто поместить JobState в исключение и дать ему тривиальный экземпляр Show.

Например:

data JobState = JobSuccess | JobFail deriving Show 
newtype JobException = JobException (MVar JobState) deriving Typeable
instance Show JobException where
    show _ = "JobException"
instance Exception JobException

exceptionHandler :: JobException -> IO ()
exceptionHandler (JobException m) = takeMVar m >>= print
person Judah Jacobson    schedule 15.09.2011