Cum de a integra / ridicare / Injectare personalizat monadă stiva cu HSpec?

voturi
1

Context

Am unele funcții monadice pentru un interpret pe care am încercat să testați cu HSpec. Ei rula cu următoarea stiva monada:

type AppState = StateT InterpreterState (ExceptT Events IO)
type AppReturn a = Either Events (a, PState)

runApp :: AppState a -> IO (AppReturn a)
runApp f = runExceptT (runStateT f new)

Iată un exemplu de unul simplu:

mustEvalExpr :: Expr -> S.AppState (S.Value)
mustEvalExpr e = do
    val <- evalExpr e
    case val of
        Just val' -> return val'
        Nothing   -> throw $ S.CannotEval e

Problema este că HSpec are propriul context ( IO ()), așa că trebuie să traducă între cele două contexte.

Abordarea curentă

Sunt folosind HSpec, și am scris o funcție de transformator pentru a obține un runAppcontext de în contextul HSpec.

-- imports omitted

extract :: S.AppReturn a -> a
extract st = case st of
    Right (a, _) -> a
    Left ev      -> throw ev

run :: (S.AppReturn a -> b) -> S.AppState a -> IO b
run extractor fn = do
    state <- S.runApp fn
    return $ extractor state

Deci , mi Specarata ca acest lucru:

spec :: Spec
spec = do
    describe mustEvalExpr $ do
        let badExpr = D.VarExpr $ D.Id doesntExist
            goodExpr = D.IntExpr 1
            val = S.IntValue 1

        it should evaluate and return expression if its a Just $ do
            (run extract $ do
                I.mustEvalExpr goodExpr
                ) >>= (`shouldBe` val)

        it should throw error if it gets a Nothing $ do
            (run extract $ do
                I.mustEvalExpr badExpr
                ) `shouldThrow` anyException

Întrebare

Este tot ce pot face? Mă simt ca run extract $ doeste bine, și cred că bine ca să fie explicit atunci când lucrurile sunt complicate.

Dar mă întrebam dacă a existat un mod în care pot integra cu HSpec, sau în cazul în care există cea mai bună practică pentru această problemă, care nu are nevoie de cod personalizat?

Întrebat 19/03/2020 la 21:58
sursa de către utilizator
În alte limbi...                            

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more