Haskell支持调试吗?

时间:2018-05-25 11:09:10

标签: debugging haskell functional-programming

例如,这是一个函数:

iffthen :: [String] -> Parser String
iffthen a = do 
x <- symbol (head a)
               y <- booleana (head (tail a))
               z <- symbol (head (tail (tail a)))
               k <- assignP (head (tail (tail (tail a))))
               l <- symbol (head (tail (tail (tail (tail a)))))
               m <- assignP (head (tail (tail (tail (tail (tail a))))))
               return k

我需要看看每个指令的真正含义

3 个答案:

答案 0 :(得分:8)

您可以使用Debug.Trace的{​​{3}}或trace :: String -> a -> a等相关功能。该函数基本上打印附加的String参数,以防函数被评估,并返回函数的结果。

因此,我们可以 - 对于可以打印的某些内容 - 附加此类trace函数,从而打印信息。请注意,Haskell中的调试通常不同于命令式语言中的调试,主要是由于懒惰:通常不评估函数,除非我们需要结果。这意味着某些函数永远不会被评估,或者在构造该函数之后很久就会对它们进行求值。

支持你的功能,我建议在这里使用模式匹配,并删除未使用变量的噪音:

iffthen :: [String] -> Parser String
iffthen (ifs : cond : thens : val1 : elses : val2 : _) = do 
    symbol ifs
    booleana cond
    symbol thens
    k <- assignP val1
    symbol elses
    assignP val2
    return k

(鉴于我正确地解释了你想要的东西,而ifsthenselses是符号,cond是条件,val1和{ {1}}是val2 - if - then表达式的值。

最好不要使用列表(因为在编译时元素的数量保证),因此构造具有特定参数的sperate类型。

答案 1 :(得分:3)

trace外,请查看traceM :: Applicative f => String -> f ()traceShowM :: (Show a, Applicative f) => a -> f ()

这些是putStrLnprint在任何monad环境中都可用的方便替换:

iffthen :: [String] -> Parser String
iffthen a = do 
x <- symbol (head a)
               traceM "booleana"
               y <- booleana (head (tail a))
               traceM "symbol 1"
               z <- symbol (head (tail (tail a)))
               traceM "assignP 1"
               k <- assignP (head (tail (tail (tail a))))
               traceM "symbol 2"
               l <- symbol (head (tail (tail (tail (tail a)))))
               traceM "assignP 2"
               m <- assignP (head (tail (tail (tail (tail (tail a))))))
               return k

如果您对每个解析器的结果感兴趣,请将traceShowId<$>等一起使用。

iffthen :: [String] -> Parser String
iffthen a = do 
x <- symbol (head a)
               y <- traceShowId <$> booleana (head (tail a))
               z <- traceShowId <$> symbol (head (tail (tail a)))
               k <- traceShowId <$> assignP (head (tail (tail (tail a))))
               l <- traceShowId <$> symbol (head (tail (tail (tail (tail a)))))
               m <- traceShowId <$> assignP (head (tail (tail (tail (tail (tail a))))))
               return k

答案 2 :(得分:0)

ghci have a stepping debugger。由于Haskell代码往往功能和懒惰,我认为它有时会导致意外。 Emacs haskell-mode曾经有debugger integration ...我想我发现该集成的作者发表评论说调试器在某种程度上存在问题,但我现在无法找到它。但是我已经尝试了一些基本示例的调试器,它的工作方式与广告一样。