csj*_*csj 2 evaluation haskell expression stream 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) ))
Run Code Online (Sandbox Code Playgroud)
输出应该是[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) ))
Run Code Online (Sandbox Code Playgroud)
在其中调用a了两个不同的变量,一个变量遮蔽了另一个变量,所以首先让我们重命名其中一个变量,以避免意外地将它们混淆:
let outer_a = 2
b = 1:[i * 2 | i <- b]
f a = 1:[i * a | i <- (f a)]
in take (outer_a+2) (f (head (tail b) ))
Run Code Online (Sandbox Code Playgroud)
现在我们可以代入outer_a并评估+:
let b = 1:[i * 2 | i <- b]
f a = 1:[i * a | i <- (f a)]
in take 4 (f (head (tail b) ))
Run Code Online (Sandbox Code Playgroud)
用以下内容重写列表推导map:
let b = 1:map (* 2) b
f a = 1:map (* a) (f a)
in take 4 (f (head (tail b) ))
Run Code Online (Sandbox Code Playgroud)
使用iterate而不是显式递归:
let b = iterate (* 2) 1
f a = iterate (* a) 1
in take 4 (f (head (tail b) ))
Run Code Online (Sandbox Code Playgroud)
评估以下两个步骤b:
let b = 1:2:iterate (* 2) 4
f a = iterate (* a) 1
in take 4 (f (head (tail b) ))
Run Code Online (Sandbox Code Playgroud)
替代b:
let f a = iterate (* a) 1
in take 4 (f (head (tail (1:2:iterate (* 2) 4)) ))
Run Code Online (Sandbox Code Playgroud)
评估tail:
let f a = iterate (* a) 1
in take 4 (f (head (2:iterate (* 2) 4) ))
Run Code Online (Sandbox Code Playgroud)
评估head:
let f a = iterate (* a) 1
in take 4 (f 2)
Run Code Online (Sandbox Code Playgroud)
替代f a:
take 4 (iterate (* 2) 1)
Run Code Online (Sandbox Code Playgroud)
评估iterate几次:
take 4 (1:2:4:8:iterate (* 2) 16)
Run Code Online (Sandbox Code Playgroud)
评估take:
[1,2,4,8]
Run Code Online (Sandbox Code Playgroud)
我们完成了。