Ich habe darüber nachgedacht, wie man scanl
zu beliebigen ADTs verallgemeinern könnte. Der Prelude-Ansatz besteht darin, alles als eine Liste zu behandeln (d. H. Foldable
) und die scanl
auf die erweiterte Ansicht der Struktur anzuwenden. Stattdessen tendiere ich dazu, an scanl
als eine Operation zu denken, die einen Zustand von jedem Knoten des Baums an seine Kinder weitergibt, während er eine monoidale Operation anwendet, wenn er von der Wurzel zu den Blättern hinwandert. So zum Beispiel auf Data.Tree
, haben wir:Ist das eine sinnvolle Verallgemeinerung von `scan`s für beliebige ADTs?
scan :: (b -> a -> b) -> b -> Tree a -> Tree b
scan fn init (Node element children)
= Node (fn init element)
$ map (treeScan fn (fn init element)) children
so dass zum Beispiel:
main = do
prettyPrint $ scan (+) 0 $
Node 1 [
Node 1 [
Node 1 [],
Node 1 []],
Node 1 [
Node 1 [],
Node 1 []]]
Ergebnisse in:
1
|
+- 2
| |
| +- 3
| |
| `- 3
|
`- 2
|
+- 3
|
`- 3
, die die gleiche ist wie scanl
durch jede Anwendung Pfad des Baumes unabhängig, Erhaltung der ursprünglichen Struktur.
Die Frage ist ziemlich einfach: Ist das eine sinnvolle Verallgemeinerung? Das heißt, wird es allgemein verwendet, mit einer kategorischen Erklärung und vielleicht mit einem anderen Namen?
Nun, es gibt ['scanl1Of'] (http://hackage.haskell.org/package/lens-4.13/docs/Control-Lens-Traversal.html#v:scanl1Of). Mit einem geeigneten 'Traversal' könnte das den Trick machen. – leftaroundabout
Ich bin mir nicht sicher, ob diese erweiterte 'scanl' die gleiche 'init' an alle Kinder weitergeben soll, wie oben beschrieben, oder kettet sie als' fold'. – chi
** chi ** ''scanl' ist' scan :: Traversable f => (b -> a -> b) -> b -> f a -> f b; scannen f z a = evalState (durchqueren (\ x -> modifizieren (flip f x) >> get) a) z '. – user3237465