2014-11-04 2 views
2

Как я могу выразить следующее без вложенных операторов case? В частности, я хотел бы сделать шаги по порядку и вызвать сбой, если какой-либо из шагов попал в «плохую» ветвь.Как я могу избежать этих случаев?

loadData :: IO [Market] 
loadData = do 
    filedata <- B.readFile "markets.json" 
    case parseData filedata of 
    Left err -> fail err 
    Right v -> do 
     case fromJSON v of 
     Error err -> fail err 
     Success a -> return a 
+0

Это должно помочь: http://en.wikibooks.org/wiki/Haskell/Monad_transformers – user3237465

ответ

2

Возможно, вы захотите, чтобы здесь был преобразован монодальный трансформатор. Что-то вроде этого (совершенно непроверенные):

import Control.Monad.Trans 
import Control.Monad.Except 

type MyMonadStack a = ExceptT String IO a 

loadData :: MyMonadStack [Market] 
loadData = do filedata <- lift $ B.readFile "markets.json" 
       v <- ExceptT $ parseData filedata 
       a <- ExceptT $ toEither $ fromJSON v 
       return a 

toEither :: WhateverTypeFromJSONReturns a b -> Either a b 
toEither (Error a) = Left a 
toEither (Success b) = Right b 
+0

Существует эта строка 'case a of {Left e -> return (Left e); Right x -> runExceptT (k x)} 'в определении bind для' ExceptT'. Таким образом, он возвращает что-то вместо сбоя с ошибкой, поэтому автору вопроса нужно определить свой собственный трансформатор монады. – user3237465

+0

@ user3237465: О, я специально не сделал этого, но забыл указать на это. В принципе, если вы ставите что-то в терминах трансформатора монады, бит 'fail' из исходного вопроса должен, вероятно, быть учтен из действия' loadData'. –

4

Если parseData и fromJSON оба имеют Either Err a как их области значений, где Err является фиксированным типом (может быть определено вами), то вы можете использовать экземпляр Either e монады как так:

loadData :: IO (Either Err [Market]) 
loadData = do 
    filedata <- B.readFile "markets.json" 
    return $ parseData filedata >>= fromJSON 

Или , если вы хотите быть лишним, вы можете использовать конкретный monad transformer, чтобы сделать то же самое.

+0

объяснение для более широкой аудитории «» в области значений этой связи может помочь Ответчик понимает этот ответ. –

+0

Мне бы хотелось услышать больше. Я не выбрал его, потому что изJSON возвращает 'Result a' вместо того, чтобы либо. http://hackage.haskell.org/package/aeson-0.6.1.0/docs/Data-Aeson.html –

+0

По codomain я имею в виду самый правый тип в конце концов -> знаки. Какой для этого идиоматический термин? Ассортимент? –