使用GHCi Haskell跟踪时,如何避免交错输出?

时间:2017-05-21 12:57:36

标签: haskell show trace

在使用Glorious Glasgow Haskell编译系统8.0.2版时,我尝试将跟踪信息添加到以下脚本中:

window.receiveMessage = function (event)
{
  alert("2");
}
addEventListener("message", receiveMessage);

但是,跟踪的输出与评估表达式import Debug.Trace init :: Show a => [a] -> [a] init l@(x:xs) | trace ( if (length l) < 2 then ( "\n\tinit [" ++ show x ++ "] = []" ) else ( "\n\tinit " ++ show l ++ " = " ++ show x ++ " : (init " ++ show xs ++ ")" ) ) False = undefined init [_] = [] init (x:xs) = x : (Main.init xs) 的输出交错,如下所示:

Main.init [2,3,5,7]

如何从输出中省略以下四行?

C:\>ghci my_script.hs
GHCi, version 8.0.2: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Main             ( my_script.hs, interpreted )
Ok, modules loaded: Main.
*Main> Main.init [2,3,5,7]

        init [2,3,5,7] = 2 : (init [3,5,7])
[2
        init [3,5,7] = 3 : (init [5,7])
,3
        init [5,7] = 5 : (init [7])
,5
        init [7] = []
]
*Main> :quit
Leaving GHCi.

我已尝试使用https://downloads.haskell.org/~ghc/6.8.1/docs/html/users_guide/interactive-evaluation.html所示的[2 ,3 ,5 ] 的几种不同版本,但无济于事。

2 个答案:

答案 0 :(得分:1)

这些行交错的原因是因为列表是Main.init函数的实际返回值。为了能够查看跟踪,您需要强制执行Main.init功能。你可以通过强制执行严格性(seqdeepseq)来做到这一点,但我认为最简单的方法就是以一种不会交错中间结果的方式使用结果。

如果您只想要没有交错数据的跟踪但最后不关心数据,那么使用sum如何使用该列表呢。

我建议你试试ghci:

λ > sum (Main.init [2,3,5,7])

    init [2,3,5,7] = 2 : (init [3,5,7])

    init [3,5,7] = 3 : (init [5,7])

    init [5,7] = 5 : (init [7])

    init [7] = []
10

其他方法

由于跟踪输出到stderr而不是stdout,您可以在命令行上拆分输出:

➜  ~ ghc temp.hs -e "Main.init [2, 3, 5, 7]" > /dev/null

    init [2,3,5,7] = 2 : (init [3,5,7])

    init [3,5,7] = 3 : (init [5,7])

    init [5,7] = 5 : (init [7])

    init [7] = []

答案 1 :(得分:1)

GHCi隐式使用print,并且是懒惰的,它会在评估列表的元素时打印它们。您可以使用强制整个列表的函数来组合它。

force :: [a] -> [a]
force xs = go xs `seq` xs
  where go [] = ()
        go (x : xs) = x `seq` go xs

在ghci:

> print . force $ init [2, 3, 5, 7]

force在deepseq库中也以更一般的形式存在, 使用它,您可以使用-interactive-printprint . force设置为默认打印机。