为什么 :sprint 总是打印“_”?
Why :sprint always prints a "_"?
Prelude> let a = 3
Prelude> :sprint a
a = _
Prelude> let c = "ab"
Prelude> :sprint c
c = _
为什么总是打印_
?我不太明白 :sprint
命令的语义。
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
Haskell 是一种懒惰的语言。在 "needed".
之前,它不会评估结果
现在,只需 打印 一个值即可使所有值变为 "needed"。换句话说,如果您在 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
,它可以让您看到到目前为止评估的内容。
我来晚了一点,但我遇到了类似的问题:
λ: let xs = [1,2,3]
xs :: Num t => [t]
λ: :sprint xs
xs = _
λ: print xs
λ: :sprint xs
xs = _
此问题特定于多态值。 如果您启用了 -XNoMonomorphismRestriction
ghci 将永远不会 evaluate/force xs
,它将只有 evaluate/force 个专业:
λ: :set -XMonomorphismRestriction
λ: let xs = [1,2,3]
xs :: [Integer]
λ: print xs
λ: :sprint xs
xs = [1,2,3]
Prelude> let a = 3
Prelude> :sprint a
a = _
Prelude> let c = "ab"
Prelude> :sprint c
c = _
为什么总是打印_
?我不太明白 :sprint
命令的语义。
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
Haskell 是一种懒惰的语言。在 "needed".
之前,它不会评估结果现在,只需 打印 一个值即可使所有值变为 "needed"。换句话说,如果您在 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
,它可以让您看到到目前为止评估的内容。
我来晚了一点,但我遇到了类似的问题:
λ: let xs = [1,2,3]
xs :: Num t => [t]
λ: :sprint xs
xs = _
λ: print xs
λ: :sprint xs
xs = _
此问题特定于多态值。 如果您启用了 -XNoMonomorphismRestriction
ghci 将永远不会 evaluate/force xs
,它将只有 evaluate/force 个专业:
λ: :set -XMonomorphismRestriction
λ: let xs = [1,2,3]
xs :: [Integer]
λ: print xs
λ: :sprint xs
xs = [1,2,3]