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

时间:2017-12-21 16:21:25

标签: list haskell

我真的不明白这个例子中scanl (\s f -> f s ) g做了什么。什么是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

2 个答案:

答案 0 :(得分:3)

来自scanl的文档:

  

scanl与foldl类似,但从左侧返回连续减少值的列表:

scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]
     

请注意   last (scanl f z xs) == foldl f z xs

所以,scanl (\s f -> f s ) g的行为如下:

scanl (\s f -> f s) g [x1, x2, ...] == [g, x1 g, x2 (x1 g), ...]

由于\s f -> f sanonymous function,它接受​​两个参数并将第二个参数应用于第一个:

 λ> (\s f -> f s) 2 (+1)
 3
 λ> (\s f -> f s) "Hello" length
 5

请注意,\s f -> f s可以写为flip ($)

所以,特别是:

run g n = scanl (\s f -> f s) g $ replicate n playRound

可以被视为:

run g n = [g, playRound g, playRound (playRound g), ...] -- Repeated n times.

答案 1 :(得分:2)

如果我们看一下documentation of scanl :: (b -> a -> b) -> b -> [a],我们会看到:

scanl :: (b -> a -> b) -> b -> [a] -> [b]
     

scanl类似于foldl,但返回连续减少的列表   左边的值:

scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]
     

请注意

last (scanl f z xs) == foldl f z xs.

所以它从n初始值z开始,每次将函数应用于z和给定列表的下一个元素。

此处初始值为g,列表为replicate n playRound(表示n个项目列表,每个项目为playRound)。这里的函数采用累加器 s和列表的元素(此处始终为playRound),以及f s的结果(在本例中为{{ 1}}),是列表中的下一个项目。

所以它会产生一个列表:

playRound s

,该列表将包含[g, playRound g, playRound (playRound g), ...] 个项目。

可能应该采用更优雅的方法:

n+1