Haskell-Let表达式求值
我正在练习计算let表达式的问题,但我不理解这个表达式的输出 下面是一个表达:Haskell-Let表达式求值,haskell,stream,expression,evaluation,let,Haskell,Stream,Expression,Evaluation,Let,我正在练习计算let表达式的问题,但我不理解这个表达式的输出 下面是一个表达: let a = 2 b = 1:[i * 2 | i <- b] f a = 1:[i * a | i <- (f a)] in take (a+2) (f (head (tail b) )) 设a=2 b=1:[i*2 | i这里有一个逐步的解释: let a = 2 b = 1:[i * 2 | i <- b] f a = 1:[i * a | i <-
let a = 2
b = 1:[i * 2 | i <- b]
f a = 1:[i * a | i <- (f a)]
in take (a+2) (f (head (tail b) ))
设a=2
b=1:[i*2 | i这里有一个逐步的解释:
let a = 2
b = 1:[i * 2 | i <- b]
f a = 1:[i * a | i <- (f a)]
in take (a+2) (f (head (tail b) ))
现在我们可以在中替换外部\u a
并计算+
:
let b = 1:[i * 2 | i <- b]
f a = 1:[i * a | i <- (f a)]
in take 4 (f (head (tail b) ))
使用迭代
而不是显式递归:
let b = iterate (* 2) 1
f a = iterate (* a) 1
in take 4 (f (head (tail b) ))
评估b
的前两个步骤:
let b = 1:2:iterate (* 2) 4
f a = iterate (* a) 1
in take 4 (f (head (tail b) ))
let f a = iterate (* a) 1
in take 4 (f (head (tail (1:2:iterate (* 2) 4)) ))
在b
中替换:
let b = 1:2:iterate (* 2) 4
f a = iterate (* a) 1
in take 4 (f (head (tail b) ))
let f a = iterate (* a) 1
in take 4 (f (head (tail (1:2:iterate (* 2) 4)) ))
评估tail
:
let f a = iterate (* a) 1
in take 4 (f (head (2:iterate (* 2) 4) ))
评估头部
:
let f a = iterate (* a) 1
in take 4 (f 2)
在f a
中替换:
take 4 (iterate (* 2) 1)
评估迭代几次:
take 4 (1:2:4:8:iterate (* 2) 16)
评估获取:
[1,2,4,8]
我们完成了。为了了解发生了什么,我们仔细命名了每个实体的名称:
let a = 2
b = 1 : [i * 2 | i <- b]
f a = 1 : [i * a | i <- f a]
in take (a+2) (f (head (tail b)))
==
let b = (b1:bs1)
(b1:bs1) = 1 : [i * 2 | i <- b]
in take 4 (f (head (tail b)))
==
let b1 = 1
bs1 = [i * 2 | i <- (b1:bs1)]
in take 4 (f (head bs1))
==
let b1 = 1
bs1 = [i * 2 | i <- [b1]] ++ [i * 2 | i <- bs1]
in take 4 (f (head bs1))
==
let bs1 = [i * 2 | i <- [1]] ++ [i * 2 | i <- bs1]
in take 4 (f (head bs1))
==
let bs1 = (b2:bs2)
(b2:bs2) = [1 * 2] ++ [i * 2 | i <- bs1]
in take 4 (f b2)
==
let (b2:bs2) = 2 : [i * 2 | i <- (b2:bs2)]
in take 4 (f b2)
==
let bs2 = [i * 2 | i <- (2:bs2)]
f a = 1 : [i * a | i <- f a] -- same as before
in take 4 (f 2)
==
let xs = f 2
f 2 = 1 : [i * 2 | i <- f 2]
in take 4 xs
==
let (x1:xs1) = 1 : [i * 2 | i <- f 2]
in take 4 (x1:xs1)
==
let xs1 = [i * 2 | i <- f 2]
in take 4 (1:xs1)
==
let xs1 = [i * 2 | i <- f 2]
in 1 : take 3 xs1
==
let (x2:xs2) = [i * 2 | i <- (y1:ys1)]
(y1:ys1) = 1 : [i * 2 | i <- f 2]
in 1 : take 3 (x2:xs2)
==
let (x2:xs2) = [i * 2 | i <- (1:ys1)]
ys1 = [i * 2 | i <- f 2]
in 1 : take 3 (x2:xs2)
==
let (x2:xs2) = 2 : [i * 2 | i <- ys1]
ys1 = [i * 2 | i <- f 2]
in 1 : take 3 (x2:xs2)
==
let xs2 = [i * 2 | i <- ys1]
ys1 = [i * 2 | i <- f 2]
in 1 : take 3 (2:xs2)
==
let xs2 = [i * 2 | i <- ys1]
ys1 = [i * 2 | i <- f 2]
in 1 : 2 : take 2 xs2
==
let (x3:xs3) = [i * 2 | i <- (y2:ys2)]
(y2:ys2) = [i * 2 | i <- (z1:zs1)]
(z1:zs1) = 1 : [i * 2 | i <- f 2]
in 1 : 2 : take 2 (x3:xs3)
==
let (x3:xs3) = [i * 2 | i <- (y2:ys2)]
(y2:ys2) = 2 : [i * 2 | i <- zs1]
zs1 = [i * 2 | i <- f 2]
in 1 : 2 : take 2 (x3:xs3)
==
let (x3:xs3) = 4 : [i * 2 | i <- ys2]
ys2 = [i * 2 | i <- zs1]
zs1 = [i * 2 | i <- f 2]
in 1 : 2 : take 2 (x3:xs3)
==
let xs3 = [i * 2 | i <- ys2]
ys2 = [i * 2 | i <- zs1]
zs1 = [i * 2 | i <- f 2]
in 1 : 2 : 4 : take 1 xs3
==
let (x4:xs4) = [i * 2 | i <- (y3:ys3)]
(y3:ys3) = [i * 2 | i <- (z2:zs2)]
(z2:zs2) = [i * 2 | i <- (w1:ws1)]
(w1:ws1) = 1 : [i * 2 | i <- f 2]
in 1 : 2 : 4 : take 1 (x4:xs4)
==
let (x4:xs4) = [i * 2 | i <- (y3:ys3)]
(y3:ys3) = [i * 2 | i <- (z2:zs2)]
(z2:zs2) = 2 : [i * 2 | i <- ws1]
ws1 = [i * 2 | i <- f 2]
in 1 : 2 : 4 : take 1 (x4:xs4)
==
let (x4:xs4) = [i * 2 | i <- (y3:ys3)]
(y3:ys3) = 4 : [i * 2 | i <- zs2]
zs2 = [i * 2 | i <- ws1]
ws1 = [i * 2 | i <- f 2]
in 1 : 2 : 4 : take 1 (x4:xs4)
==
let (x4:xs4) = 8 : [i * 2 | i <- ys3]
ys3 = [i * 2 | i <- zs2]
zs2 = [i * 2 | i <- ws1]
ws1 = [i * 2 | i <- f 2]
in 1 : 2 : 4 : take 1 (x4:xs4)
==
1 : 2 : 4 : 8 : take 0 xs4
==
1 : 2 : 4 : 8 : []
这实际上是一个即将到来的考试的练习题,答案据说是[1,2,4,8]@csj,那么要么练习题是错的,要么你抄错了。如果你在GHCi中键入你在问题中发布的内容(当然在执行:set+m
之后),它会给你[1,3,9,27]
。哦,我很抱歉它应该是*而不是+对于b,我刚刚编辑了问题fa
返回的值当然与iterate(*a)1
返回的值相同,但是它以一种非常不同的、非常慢的方式(是二次的,而不是线性的)。如果我们一步一步地减少它,就可以看出这一点。
[ ... | ... <- (xs ++ ys)]
===
[ ... | ... <- xs ] ++ [ ... | ... <- ys]
[ ... | ... <- (x : ys)]
===
[ ... | ... <- [x] ] ++ [ ... | ... <- ys]
> f 1.01 !! 4000
1.9297236994732192e17
(1.28 secs, 1614556912 bytes)
> iterate (* 1.01) 1 !! 4000
1.9297236994732192e17
(0.00 secs, 12990984 bytes)