Haskell seq到达构造函数后立即停止

Haskell seq到达构造函数后立即停止,haskell,Haskell,说明seq一到达构造函数就停止 case1 = 1:repeat undefined `seq` "OK" case2 = (undefined,undefined) `seq` "OK" 我们有 1:repeat undefined = (:) 1 (repeat undefined) (undefined,undefined) = (,) undefined undefined 我理解为什么case1函数返回“OK”。 但是为什么case2函数也返回“OK”? 我认为案例2将返回“Pre

说明seq一到达构造函数就停止

case1 = 1:repeat undefined `seq` "OK"
case2 = (undefined,undefined) `seq` "OK"
我们有

1:repeat undefined = (:) 1 (repeat undefined)
(undefined,undefined) = (,) undefined undefined
我理解为什么case1函数返回“OK”。 但是为什么case2函数也返回“OK”? 我认为案例2将返回“Preluded.undefined”,因为在第一个案例中,1被计算,所以我认为在第二个案例中,undefined也应该被计算

但是为什么case2函数也返回“OK”

因为两个
未定义的
都在
(,)
构造函数中,因此不进行计算

我认为案例2将返回“Preluded.undefined”,因为在第一个案例中,对1进行了评估

1
在第一种情况下不进行求值-正如书中所说,求值以
(:)
(第一个构造函数)停止<代码>未定义:未定义的'seq`“OK”
仍然计算为“OK”。

RWH说

考虑值
(1+2):(3+4):[]
。如果我们对此应用
seq
,它将评估
(1+2)
thunk

这是不正确的,Phil Thomas在在线版本中的评论指出:

在ghci中,如果输入以下内容:

let x = (1+2):(3+4):[]
seq x True
:print x
你会看到:

x = [(_t1::Integer),(_t2::Integer)]
尚未评估
(1+2)
。cons是一个中缀运算符,似乎位于
(1+2)
之后,但它实际上是seq遇到的第一件事

我们可以将
seq
定义为:

⊥ `seq` b = ⊥
a `seq` b = b
为了确定某个值是否为底部,必须仅对其最外层的构造函数求值。
1:repeat undefined
的最外层构造函数不是
1
,而是
(:)
。例如,您可以将
1:[]
可视化为:

 (:)
 / \
1   []
此表示中最外层的构造函数是最顶层的构造函数

case1 = 1:repeat undefined `seq` "OK"
case2 = (undefined,undefined) `seq` "OK"
这意味着
1:repeat undefined
将被计算为
\uu:
,而不是
1:\u
(其中
\u
表示未计算的thunk)


类似地,
(未定义,未定义)
的最外层构造函数是
(,)
,它将被求值为
(,,)
,而不是
(未定义,未定义)
未定义的

RHW表示“考虑值(1+2):(3+4):[]。如果我们将seq应用于此,它将求值为(1+2)thunk–所以我认为1应该被计算。
1+2
与你的问题中的
(,)12
(,)未定义的未定义的未定义的
不一样。一个是计算,另一个是数据构造。@neo2500这在书中似乎是一个错误。
未定义的:(3+4):[]`seq`“OK”
计算为“OK”“-肯定不会计算
的左操作数。@ThomasM.DuBuisson但
(1+2):…
(1+2…)
相同(就表达式相对于构造函数的位置而言)。书中的这一行似乎是错的(或者neo和我都误读了)。@neo2500这本书并不清楚“将
seq
应用于此”是什么意思
seq(1+2)“OK”
会将
1+2
求值为
3
,但您可以在GHCi中检查
(1+2):(3+4):[]
seq“OK”`不会求值列表中的任何元素:
>让x=(1+2):(3+4):[];>顺序x“确定”;>:sprint x-->x=\uu