I'm trying to write an interpreter for a simple embedded scripting language.
The core of it is the eval function, which has the following signature.
type EvalState = () --for later
type EvalResult = State EvalState (IO (Either T.Text Value))
eval :: Expr -> EvalResult
The result type is like this because it is statefull, eval should be able todo IO and it can fail.
There are two datatypes: Expressions and Values and eval converts expression to values. For simple expressions, literals of primitive data types, it's implemented like this:
ok :: Value -> EvalResult
ok val = state (return . Right $ val,)
eval :: Expr -> EvalResult
eval (StrLit t) = ok (StrVal t)
eval (SymLit t) = ok (SymbolVal t)
eval (IntLit i) = ok (IntVal i)
eval (FloatLit f) = ok (FloatVal f)
My problem now is implementing eval for the list literal. Currently my code looks like this:
eval (ListLit elems) = do
elems <- mapM eval elems
do
opts <- sequence elems
return $ fmap (Right . ListVal . V.fromList) (sequence opts)
And this produces the following error:
/home/felix/git/vmail/src/Interpreter/EvalAst.hs:37:13: error:
• Couldn't match type ‘IO’
with ‘StateT EvalState Data.Functor.Identity.Identity’
Expected: StateT
EvalState Data.Functor.Identity.Identity [Either T.Text Value]
Actual: IO [Either T.Text Value]
• In a stmt of a 'do' block: opts <- sequence elems
In a stmt of a 'do' block:
do opts <- sequence elems
fmap (Right . ListVal . V.fromList) (sequence opts)
In the expression:
do elems <- mapM eval elems
do opts <- sequence elems
fmap (Right . ListVal . V.fromList) (sequence opts)
|
37 | opts <- sequence elems
| ^^^^^^^^^^^^^^
My problem is that I'm not understanding this error. My thinking goes like this: the first do puts me in the State monad, so I shold be able to "extract" the results from mapM eval elems which I expect to be [ IO (Either ...) ] The next do should put me in the IO monad (because that's the next inner type in the result type), so I should be able to extract IO values, and as far as I understood it, sequence elems should give me a IO [ Either ... ] which I can then extract, so what is my mistake?