Как интегрировать / поднять / внедрить пользовательский стек монад с HSpe c? - PullRequest
1 голос
/ 19 марта 2020

Context

У меня есть несколько функций monadi c для интерпретатора, которые я пытаюсь проверить с помощью HSpe c. Они работают со следующим стеком монад:

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)

Вот простой пример:

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

Проблема в том, что HSpe c имеет свой собственный контекст (IO () ), поэтому мне приходится переводить между двумя контекстами.

Текущий подход

Я использую HSpe c, и я написал функцию преобразователя для получения контекста runApp изнутри контекст HSpe c.

-- 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

Итак, мой Spec выглядит следующим образом:

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

Вопрос

Это лучшее, что я могу сделать? Я чувствую, что run extract $ do - это хорошо, и я думаю, что хорошо быть понятным, когда все сложно.

Но мне было интересно, есть ли способ, которым я могу интегрироваться с HSpe c, или есть ли наилучшая практика для этой проблемы, которая не требует специального кода?

...