2017-12-21 4 views
1

Ich verstehe wirklich nicht, was macht in diesem Beispiel tun. Was ist f?Was bewirkt die folgende Funktion? (scanl)

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

'f' der zweite Parameter des Lambda-Ausdruck ist. –

Antwort

3

Aus der Dokumentation für scanl:

scanl ist ähnlich, foldl aber eine Liste von aufeinanderfolgenden reduzierten Werte von links zurück:

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

Beachten Sie, dass last (scanl f z xs) == foldl f z xs.

So verhält sich scanl (\s f -> f s) g wie folgt aus:

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

Da \s f -> f s ein anonymous function ist, die zwei Argumente übernimmt und wendet die zweite auf die erste:

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

Beachten Sie, dass \s f -> f s geschrieben werden als flip ($).


Also, speziell:

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

könnte als zu sehen:

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

Wenn wir die documentation of scanl :: (b -> a -> b) -> b -> [a] schauen wir sehen, dass:

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

scanl foldl ist ähnlich, aber gibt eine Liste von aufeinanderfolgenden reduziert Werte von links:

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

Beachten Sie, dass

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

So beginnt es mit n Anfangswert z, und jedes Mal, es gilt eine Funktion zu z und das nächste Element der angegebenen Liste.

Hier ist der Anfangswert ist g, und die Liste ist replicate n playRound (die eine Liste von n Elemente bedeutet, jedes Element ist playRound). Die Funktion nimmt hier den Akkus, und ein Element der Liste (hier immer playRound), und das Ergebnis f s (in diesem Fall playRound s), ist das nächste Element in der Liste.

So wird es eine Liste erzeugen:

[g, playRound g, playRound (playRound g), ...] 

und die Liste n+1 Artikel enthalten wird.

Wahrscheinlich ein eleganter Ansatz hätte sein sollen:

run :: Grid -> Int -> [Grid] 
run g n = take (n+1) $ iterate playRound g 
Verwandte Themen