刚性类型错误与IO和多态类型相结合

时间:2013-04-20 15:13:09

标签: haskell

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

整个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的家伙们变得越来越好,但这个让我完全难过。如何“Actualy类型”Var - > Val - > Vars - > o哪个是多态的而不是特定的?

注意:如果我需要提供更多信息请告诉我 - 我已经尽可能少地开始,所以我不会给那些不必要信息的人带来负担

1 个答案:

答案 0 :(得分:4)

电话(interpret_statement prog debug_function vars x)处于必须返回Vars的位置,它无法返回o类型。

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

我的Haskell有点生疏,但我相信您可以更改interpret_function以便其类型变为

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

其中m将是IO或一些琐碎的monad(perhaps this one)。

现在该特定案例的实施将是这样的:

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