1

我正在为一种简单的语言编写解释器作为大学项目,并且可以选择编写一些调试功能。我认为这很简单,但由于沮丧而休息了大约一周后,我回来处理这个问题。

整个 haskell 文件大约有 250 行,所以我不想发布整个内容,但如果我没有提供足够的信息,请告诉我。

我有这个功能

interpret_statement :: Prog -> (Var -> Val -> Vars -> o) -> Vars -> Stmt -> o

其中 (Var -> Val -> Vars -> o) 是调试功能 - 我选择的两种可能性之一

pure_passthrough :: Var -> Val -> Vars -> Vars -- does no IO
write_debugging_info :: Var -> Val -> Vars -> IO Vars -- does IO

我还有另一个功能

interpret_function :: Prog -> (Var -> Val -> Vars -> o) -> Vars -> [Stmt] -> Val

其中包含一行

interpret_function prog debug_function vars (x:xs) = interpret_function prog debug_function (interpret_statement prog debug_function vars x) xs 

并且是 3 行之一,它给了我一个严格的类型错误,说

Expected type: Var -> Val -> Vars -> Vars
Actual type: Var -> Val -> Vars -> o

在尝试引入 IO 之前,一切都运行良好。我这样做是因为这个站点上的一个单独问题的答案建议我使用多态函数来告诉程序是否在运行时执行 IO,具体取决于我是否收到命令行参数。

但是现在它会引起问题,因为我现在需要将多态变量传入和传出几个相互依赖的函数?哦人类!我真的认为我在 Haskell 方面做得越来越好,但这个让我完全难过。“实际类型” Var -> Val -> Vars -> o 是多态的而不是真正具体的?

注意:如果我需要包含更多信息,请告诉我 - 我已经尽可能少地开始,所以我不会让人们使用不必要的信息

4

1 回答 1

4

调用(interpret_statement prog debug_function vars x)处于它必须返回的位置Vars,它不能返回类型o

interpret_function中,返回类型不依赖于o,所以即使你传入一个返回 IO monad 的调试函数, 的结果interpret_function也不是 IO monad。

我的 Haskell 有点生锈,但我相信你可以改变interpret_function它的类型

interpret_function :: (Monad m) => Prog -> (Var -> Val -> Vars -> m Vars) -> Vars -> [Stmt] -> m Val

哪里m将是IO或者一些微不足道的单子(也许是这个)。

现在,该特定案例的实现将如下所示:

interpret_function prog debug_function vars (x:xs) =
  do vars' <- interpret_statement prog debug_function vars x
     return $ interpret_function prog debug_function vars' xs
于 2013-04-20T15:50:01.017 回答