我真的不明白这个例子中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
答案 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 s
是anonymous 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