[英]What does the following function do? (scanl)
I really don't understand what does scanl (\\sf -> fs ) g
do in this example. 我真的不明白在这个例子中scanl (\\sf -> fs ) g
做什么的。 What is f
? 什么是f
?
data Grid = Grid [Line]
data CellState = Dead | Alive deriving (Eq)
data Cell = Cell CellState Int deriving (Eq)
data Line = Line [Cell] Int deriving (Eq)
run :: Grid -> Int -> [Grid]
run g n = scanl (\s f -> f s) g $ replicate n playRound
playRound :: Grid -> Grid
From the documentation for scanl
: 从scanl
的文档中:
scanl is similar to foldl, but returns a list of successive reduced values from the left: scanl与foldl相似,但是从左侧返回一个连续减小值的列表:
scanl fz [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]
Note that
last (scanl fz xs) == foldl fz xs
. 注意last (scanl fz xs) == foldl fz xs
。
So, scanl (\\sf -> fs ) g
behaves like this: 因此, scanl (\\sf -> fs ) g
行为如下:
scanl (\s f -> f s) g [x1, x2, ...] == [g, x1 g, x2 (x1 g), ...]
Since \\sf -> fs
is an anonymous function which takes two arguments and applies the second to the first: 由于\\sf -> fs
是一个匿名函数 ,它接受两个参数并将第二个参数应用于第一个参数:
λ> (\s f -> f s) 2 (+1)
3
λ> (\s f -> f s) "Hello" length
5
Note that \\sf -> fs
could be written as flip ($)
. 注意\\sf -> fs
可以写成flip ($)
。
So, specifically: 因此,具体来说:
run g n = scanl (\s f -> f s) g $ replicate n playRound
Could be seen as: 可以看作是:
run g n = [g, playRound g, playRound (playRound g), ...] -- Repeated n times.
If we look at the documentation of scanl :: (b -> a -> b) -> b -> [a]
we see that: 如果我们看一下scanl :: (b -> a -> b) -> b -> [a]
的文档,我们会看到:
scanl :: (b -> a -> b) -> b -> [a] -> [b]
scanl is similar to foldl, but returns a list of successive reduced values from the left: scanl与foldl相似,但是从左侧返回一个连续减小值的列表:
scanl fz [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]
Note that 注意
last (scanl fz xs) == foldl fz xs.
So it starts with n initial value z
, and each time it applies a function to z
and the next element of the given list. 因此它以n初始值z
开头,并且每次将函数应用于z
和给定列表的下一个元素。
Here the initial value is g
, and the list is replicate n playRound
(which means a list of n
items, each item is playRound
). 这里的初始值是g
,列表是replicate n playRound
(这意味着n
项目的列表,每个项目都是playRound
)。 The function here takes the accumulator s
, and an element of the list (here always playRound
), and the outcome of fs
(in this case playRound s
), is the next item in the list. 此处的函数采用累加器 s
,列表中的下一个项目是列表中的元素(此处始终为playRound
)和fs
的结果(在本例中为playRound s
)。
So it will produce a list: 因此它将产生一个列表:
[g, playRound g, playRound (playRound g), ...]
and the list will contain n+1
items. 并且该列表将包含n+1
项目。
Probably a more elegant approach should have been: 可能更优雅的方法应该是:
run :: Grid -> Int -> [Grid]
run g n = take (n+1) $ iterate playRound g
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.