(x*)中的星号在Haskell中有什么作用?
我是 Haskell 的新手,有人可以向我解释这段代码是如何工作的吗?
f = g (x -> x)
g k [] = k 100
g k (x:xs) = g ((x*) . k) xs
当我调用f [1..5]它时返回 12000。我不明白为什么。有什么作用(x*)?
回答
您可以扩展定义,并观察发生了什么。
f [1..5]
= g (x -> x) [1..5]
= g ((1*) . (x -> x)) [2..5]
= g ((2*) . (1*) . (x -> x)) [3..5]
= g ((3*) . (2*) . (1*) . (x -> x)) [4..5]
= g ((4*) . (3*) . (2*) . (1*) . (x -> x)) [5]
= g ((4*) . (3*) . (2*) . (1*) . (x -> x)) [5]
= g ((5*) . (4*) . (3*) . (2*) . (1*) . (x -> x)) []
= ((5*) . (4*) . (3*) . (2*) . (1*) . (x -> x)) 100
= ((5*) . (4*) . (3*) . (2*) . (1*)) 100
= ((5*) . (4*) . (3*) . (2*)) 100
= ((5*) . (4*) . (3*)) 200
= ((5*) . (4*)) 600
= (5*) 2400
= 12000
注意(x*)是函数“乘以x”,即y -> x*y,而运算符.是函数组合。所以组合链(5*) . (4*) . ... . (1*)是“将输入乘以 1,然后乘以 2,然后乘以 3,......,然后乘以 5”的函数。
您的代码是以所谓的延续传递风格 (CPS) 编写的,我们不是从初始值 (100) 开始并对其应用函数,而是执行(尾)递归调用并将一些函数“附加”到当前的“延续” k((x*) . k在您的代码中使用)。这样做会构建一个很长的组合函数链,并且只有在最后我们才将该链应用到初始值 (100)。一般来说,这种代码风格不是特别容易阅读。