Haskell 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) ))

输出应该是[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) ))

其中有两个不同的变量,称为 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) ))

现在我们可以替换 outer_a 并计算 +:

let b = 1:[i * 2 | i <- b]
    f a = 1:[i * a | i <- (f a)]
in take 4 (f (head (tail b) ))

根据map重写列表推导式:

let b = 1:map (* 2) b
    f a = 1:map (* a) (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) ))

替换为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) ))

评估head:

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]

我们就完成了。

关于Haskell Let 表达式求值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55715331/

相关文章:

c++ - "True Polymorphism"的例子? (最好使用 Haskell)

haskell - 如何修复 '*** Exception: Prelude.head: empty list' 这里

haskell - 尝试将映射应用于 Haskell 中函数的 "inner"参数

c++ - 如何在不跳过空行的情况下从文件中读取一行文本?

go - 如果我的类型作为流没有意义,是否应该实现io.Reader/io.Writer?

c++ - 表达式 (a=b) = k UB?

regex - Perl:正则表达式的最大值?

haskell - 纯函数中的跟踪输出

c++ - 如何在 C++ 中将输入流的前缀复制到不同的流?

javascript - Angularjs 使用表达式进行验证