首页 文章

打开Haskell State Monad

提问于
浏览
5

在为大学编写作业的过程中,我有学习新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 回答

  • 11

    compile progState VarsState monad中的一个动作,因此您无法在 IO -do-block中使用它 . 在do-block中,所有行必须使用相同的monad,在本例中为 IO .

    你需要"run" compile 动作来获得结果,其中一个

    runState :: State s a -> s -> (a,s)
    evalState :: State s a -> s -> a
    execState :: State s a -> s -> s
    

    取决于您是否需要

    • ,结果和最终状态

    • 结果

    • 只有最终状态

    在您的情况下,您只需要结果,所以它是 evalState .

    为此你需要提供一个初始状态,它可能看起来像

    maybe_compile_prog (OK prog) modulename = do
        let s1 = evalState (compile prog) initialState
        writeFile (modulename ++ ".m") ((header modulename) ++ s1)
    

    但是, compile 动作提供的初始状态对于所有传递的_218894都是相同的 . 如果这不是正确的事情,您也可以将初始状态作为参数传递 .

相关问题