Haskell让表达式评估

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]。有人可以一步一步解释为什么这是输出

Jos*_*ica 6

以下是分步说明:

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)

我们完成了。

  • @csj然后实践问题是错误的,或者您将其复制到错误的位置。如果您输入的是您问题中所输入的内容(当然,在执行`:set + m`之后),它将为您提供[[1,3,9,27]]。 (3认同)