简体   繁体   English

以下功能有什么作用? (扫描)

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM