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

vik*_*ata 15 debugging haskell lazy-evaluation ghci

Prelude> let a = 3
Prelude> :sprint a
a = _
Prelude> let c = "ab"
Prelude> :sprint c
c = _
Run Code Online (Sandbox Code Playgroud)

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

Mat*_*hid 14

Haskell是一种懒惰的语言.在"需要"之前,它不会评估结果.

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

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

例如:

Prelude> let xs = [1..]
Prelude> :sprint xs
xs = _
Run Code Online (Sandbox Code Playgroud)

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

Prelude> head xs
1
Prelude> :sprint xs
xs = 1 : _
Run Code Online (Sandbox Code Playgroud)

现在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 : _
Run Code Online (Sandbox Code Playgroud)

现在评估前10个元素,但仍有更多元素.(因为这xs是一个无限的列表,这并不奇怪.)

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

  • 备注:由于`[1 ..]`具有多态类型,所以`:sp xs`很可能产生`_`,即使在`head xs`之后.`let xs = [1 ..] :: [Integer]`将解决这个问题. (19认同)

Seb*_*edl 6

哈斯克尔很懒.它不会在需要之前对事物进行评估.

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

当你写作

let a = 3
Run Code Online (Sandbox Code Playgroud)

你将一个新名称绑定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
Run Code Online (Sandbox Code Playgroud)

  • 对于`let a = 3`它更复杂(你应该尝试这个) - 默认情况下`a`将是`a :: Num a => a`并且在你的情况下将始终`:sprint` to`_` - IMO `String`示例更适合对此感觉 (11认同)
  • 如果你使用`let a = 3`,你最好指定一个类型`let a = 3 :: Int`,这样你就不会感到困惑,同时注意这个行为在GHC 7.8中已经改变,在旧版本中你不必写这句话中的类型使`:sprint`作为'expected'工作. (7认同)

Nic*_*tia 6

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

?: let xs = [1,2,3]
xs :: Num t => [t]
?: :sprint xs
xs = _
?: print xs
?: :sprint xs
xs = _
Run Code Online (Sandbox Code Playgroud)

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

?: :set -XMonomorphismRestriction
?: let xs = [1,2,3]
xs :: [Integer]
?: print xs
?: :sprint xs
xs = [1,2,3]
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这仅适用于像'xs`这样的"重载"值.具有变量类型并且对这些变量具有类型类约束的事物.它主要只是涉及文字数字的例子,这种行为方式; 不幸的是,在学习的过程中,数字是很明显的事情.如果您改为使用布尔值("True","False","&&","和"等),那么无论"NoMonomorphismRestriction"是什么,或者您是否给出明确的类型签名,所有内容的行为都大致相同. (2认同)