【问题标题】:Understanding how :sprint and list evaluation works in haskell了解 :sprint 和 list 评估如何在 haskell 中工作
【发布时间】:2016-08-17 10:57:40
【问题描述】:

我正在处理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 ':' 构造函数在其元素上递归创建列表)

【问题讨论】:

    标签: list haskell evaluation


    【解决方案1】:

    :sprint 的行为可能有点棘手。这种情况下看x的类型:

    > :t x
    x :: Num t => [t]
    

    因为它是多态的,所以产生的实际值取决于您需要的 Num 的特定实例。因此,x 的行为更像是一个生成列表 [1,2,3,4,5] 的函数,当它可以确定您希望元素具有什么类型时。

    现在你可能会想,“好吧,我会做一个非多态的列表”,所以你试试这个:

    > 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 中比较棘手的事情之一(当它变得重要时)。

    【讨论】:

    • 如果您使用:set -XMonomorphismRestriction,第一个问题就会消失。使用:sprint 的一些示例,例如在 Parallel and Concurrent Haskell 一书中,早于 ghci 中默认使用 -XNoMonomorphismRestriction,因此会产生这个麻烦。在摆弄:sprint
    • 适当注明。感谢您的提示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-19
    • 2013-04-09
    • 1970-01-01
    • 2010-12-06
    相关资源
    最近更新 更多