在为大学编写作业的过程中,我有学习新Haskell monad的快乐乐趣 . 好极了!!!
我有一个typechecks很好的功能:
compile :: Prog -> State VarsState String
compile prog@(Prog functions) = do
s1 <- sequence (map (translate_func 0) [get_function prog name | name <- [func_name func | func <- functions]])
return $ trace ("here's the program: \n" ++ show prog) $ concat $ s1
但当这个其他功能:
maybe_compile_prog ::
MaybeOK Prog -> String -> IO ()
maybe_compile_prog (Error msg) _ = do
putStrLn ("error: " ++ msg)
maybe_compile_prog (OK prog) modulename = do
s1 <- compile prog
writeFile (modulename ++ ".m") ((header modulename) ++ s1)
试图称之为它,它在线上爆炸
s1 <- compile prog
说它无法将预期类型“IO t0”与实际类型“State VarsState String”匹配 .
我假设这是因为maybe_compile_prog返回类型IO()所以它只希望解包IO信息? VarsState是我与State monad一起使用的自定义数据类型/
但是,如果这是问题,我认为是,我不知道如何将这个简单的字符串传递给maybe_compile_prog . 真的,这就是我想做的 - 给maybe_compile_prog一个字符串 .
也许有一些简洁的方法解开这个状态monad?也许有可能重写“编译”,以便它在运行时接收一些状态monad信息,但然后只返回一个字符串(不包含在任何monad中)?
如果我遗漏任何信息,请告诉我 .
1 回答
compile prog
是State VarsState
monad中的一个动作,因此您无法在IO
-do-block中使用它 . 在do-block中,所有行必须使用相同的monad,在本例中为IO
.你需要"run"
compile
动作来获得结果,其中一个取决于您是否需要
,结果和最终状态
仅
结果
只有最终状态
在您的情况下,您只需要结果,所以它是
evalState
.为此你需要提供一个初始状态,它可能看起来像
但是,
compile
动作提供的初始状态对于所有传递的_218894都是相同的 . 如果这不是正确的事情,您也可以将初始状态作为参数传递 .