了解 :sprint 和列表评估在 haskell 中的工作原理
Understanding how :sprint and list evaluation works in haskell
我正在研究 haskell book,我了解到 :sprint x
用于打印 x 的元素已被求值而元素未被求值(未被表达的元素通过'_')。
书中提供的例子之一,
Prelude> let blah = enumFromTo 'a' 'z'
Prelude> :sprint blah
blah = _
Prelude> take 1 blah
"a"
Prelude> :sprint blah
blah = 'a' : _
为了测试不同的输入,我在 GHCi 中做了这个:-
prelude> let b = [1,2,3,4,5]
prelude> :sprint b
b = _
prelude> take 1 b
[1]
prelude> :sprint b
b = _
最后一个命令中 :sprint b
的输出不应该是 b = 1 : _
因为我们在使用命令 take 1 b
时只评估单个列表项和一个 cons 运算符?但它显示了上面的输出。这是怎么发生的,为什么会发生?输出不应该类似于String类型的输出吗?
编辑:我进行了更多试验并得到了这个结果:-
prelude> let b = [1..10] :: [Int]
prelude> :sprint b
b = _
prelude> take 3 b
[1,2,3]
prelude> :sprint b
b = 1 : 2 : 3 : _
好吧,我最初的猜测是,这是因为我构建这两个列表的方式?一种是使用范围,另一种是通过显式声明其元素(这反过来通过在其元素上递归地使用 cons ':' 构造函数来创建列表)
:sprint
的行为可能有点棘手。在这种情况下,查看 x
的类型:
> :t x
x :: Num t => [t]
因为它是多态的,所以生成的实际值取决于您需要的 Num
的特定实例。因此,x
的行为更像是一个生成列表 [1,2,3,4,5]
的函数,它可以确定您希望元素具有的类型。
现在你可能会想,"ok, I'll make a list that isn't polymorphic",所以你试试这个:
> let x = [1,2,3,4,5 :: Int]
> :t x
x :: [Int]
> :sprint x
x = [1,2,3,4,5]
到底是什么?如果你仔细想想,这是有道理的。我们已经明确地告诉 ghci 列表是什么。这不像它可以取消评估然后稍后重新评估它。 (无论如何这都是浪费。)但是让我们看看当我们尝试将函数映射到 x:
时会发生什么
> let y = map (+1) x
> :sprint y
y = _
> take 1 y
[2]
> :sprint y
y = 2 : _
果然不出所料!
希望对您有所帮助。惰性评估是 Haskell 中比较棘手的事情之一(当它变得重要时)。
我正在研究 haskell book,我了解到 :sprint x
用于打印 x 的元素已被求值而元素未被求值(未被表达的元素通过'_')。
书中提供的例子之一,
Prelude> let blah = enumFromTo 'a' 'z'
Prelude> :sprint blah
blah = _
Prelude> take 1 blah
"a"
Prelude> :sprint blah
blah = 'a' : _
为了测试不同的输入,我在 GHCi 中做了这个:-
prelude> let b = [1,2,3,4,5]
prelude> :sprint b
b = _
prelude> take 1 b
[1]
prelude> :sprint b
b = _
最后一个命令中 :sprint b
的输出不应该是 b = 1 : _
因为我们在使用命令 take 1 b
时只评估单个列表项和一个 cons 运算符?但它显示了上面的输出。这是怎么发生的,为什么会发生?输出不应该类似于String类型的输出吗?
编辑:我进行了更多试验并得到了这个结果:-
prelude> let b = [1..10] :: [Int]
prelude> :sprint b
b = _
prelude> take 3 b
[1,2,3]
prelude> :sprint b
b = 1 : 2 : 3 : _
好吧,我最初的猜测是,这是因为我构建这两个列表的方式?一种是使用范围,另一种是通过显式声明其元素(这反过来通过在其元素上递归地使用 cons ':' 构造函数来创建列表)
:sprint
的行为可能有点棘手。在这种情况下,查看 x
的类型:
> :t x
x :: Num t => [t]
因为它是多态的,所以生成的实际值取决于您需要的 Num
的特定实例。因此,x
的行为更像是一个生成列表 [1,2,3,4,5]
的函数,它可以确定您希望元素具有的类型。
现在你可能会想,"ok, I'll make a list that isn't polymorphic",所以你试试这个:
> let x = [1,2,3,4,5 :: Int]
> :t x
x :: [Int]
> :sprint x
x = [1,2,3,4,5]
到底是什么?如果你仔细想想,这是有道理的。我们已经明确地告诉 ghci 列表是什么。这不像它可以取消评估然后稍后重新评估它。 (无论如何这都是浪费。)但是让我们看看当我们尝试将函数映射到 x:
时会发生什么> let y = map (+1) x
> :sprint y
y = _
> take 1 y
[2]
> :sprint y
y = 2 : _
果然不出所料!
希望对您有所帮助。惰性评估是 Haskell 中比较棘手的事情之一(当它变得重要时)。