为什么:sprint总是打印一个" _"?

时间:2016-02-04 10:19:39

标签: debugging haskell lazy-evaluation ghci

Prelude> let a = 3
Prelude> :sprint a
a = _
Prelude> let c = "ab"
Prelude> :sprint c
c = _

为什么总是打印_?我不太了解:sprint命令的语义。

3 个答案:

答案 0 :(得分:14)

Haskell是一种懒惰的语言。它不会评估结果,直到它们需要"。

现在,只需打印一个值就会导致所有这些都需要"需要"。换句话说,如果在GHCi中键入表达式,它将尝试打印出结果,这会导致全部被评估。通常这就是你想要的。

sprint命令(GHCi功能,不是Haskell语言的一部分)允许您查看此时已评估了多少值。

例如:

Prelude> let xs = [1..]
Prelude> :sprint xs
xs = _

所以,我们刚刚宣布xs,而且它目前尚未评估。现在让我们打印出第一个元素:

Prelude> head xs
1
Prelude> :sprint xs
xs = 1 : _

现在,GHCi评估了该名单的负责人,但仅此而已。

Prelude> take 10 xs
[1,2,3,4,5,6,7,8,9,10]
Prelude> :sprint xs
xs = 1 : 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 : 10 : _

现在评估前10个元素,但仍有更多元素。 (由于xs无限列表,这并不奇怪。)

您可以构建其他表达式并一次评估它们以查看正在进行的操作。这实际上是GHCi调试器的一部分,它允许您一次一步地执行代码。特别是如果您的代码陷入无限循环,您不希望print任何东西,因为这可能会锁定GHCi。但是你仍然希望看到发生了什么...因此sprint,它可以让你看到到目前为止所评估的内容。

答案 1 :(得分:6)

Haskell很懒。在需要之前,它不会对事物进行评估。

GHCi sprint命令(不是Haskell的一部分,只是解释器的调试命令)打印表达式的值而不强制进行评估。

写作时

let a = 3

您将新名称a绑定到右侧表达式,但Haskell尚未评估该内容。因此,当您sprint时,它会打印_作为值,以指示表达式尚未被评估。

试试这个:

let a = 3
:sprint a -- a has not been evaluated yet
print a -- forces evaluation of a
:sprint a -- now a has been evaluated

答案 2 :(得分:6)

我有点晚了,但我遇到了类似的问题:

λ: let xs = [1,2,3]
xs :: Num t => [t]
λ: :sprint xs
xs = _
λ: print xs
λ: :sprint xs
xs = _

此问题特定于多态值。如果您启用-XNoMonomorphismRestriction ghci将永远不会真正评估/强制xs,它只会评估/强制专业化:

λ: :set -XMonomorphismRestriction
λ: let xs = [1,2,3]
xs :: [Integer]
λ: print xs
λ: :sprint xs
xs = [1,2,3]