Como integrar / elevador / injetar pilha mônada personalizado com HSpec?

votos
1

Contexto

Eu tenho algumas funções monádicas para um intérprete que eu estou tentando teste com HSpec. Eles correm com a seguinte pilha de mônada:

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)

Aqui está um exemplo de um simples:

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

O problema é que HSpec tem seu próprio contexto ( IO ()), então eu tenho que traduzir entre os dois contextos.

Abordagem atual

Estou usando HSpec, e eu escrevi uma função transformador para obter um runAppcontexto de dentro do contexto 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

Então, meus Specolhares como este:

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

Questão

É este o melhor que eu posso fazer? Eu sinto que run extract $ doé bom, e eu acho que é bom para ser explícita quando as coisas são complicadas.

Mas eu queria saber se havia uma maneira que eu possa integrar com HSpec, ou se há uma melhor prática para este problema que não requer código personalizado?

Publicado 19/03/2020 em 21:58
fonte usuário
Em outras línguas...                            

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