Zastanawiam się, w jaki sposób można uogólnić scanl
na arbitralne ADT. Podejście Prelude ma traktować wszystko jako listę (tj. Foldable
) i zastosować scanl
w płaskim widoku struktury. Zamiast tego, myślę o scanl
jako operacji, która przechodzi stan z każdego węzła drzewa do jego dzieci, podczas stosowania operacji monoidal op, gdy przemieszcza się od korzenia do liści. Tak więc, na przykład, na Data.Tree
, mamy:Czy jest to znaczące uogólnienie "skanów" dla arbitralnych ADT?
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
tak, że na przykład:
main = do
prettyPrint $ scan (+) 0 $
Node 1 [
Node 1 [
Node 1 [],
Node 1 []],
Node 1 [
Node 1 [],
Node 1 []]]
Wyniki w:
1
|
+- 2
| |
| +- 3
| |
| `- 3
|
`- 2
|
+- 3
|
`- 3
który jest taki sam jak stosowanie scanl
przez każdy ścieżka drzewa niezależnie, zachowując oryginalną strukturę.
Pytanie jest raczej proste: czy jest to znaczące uogólnienie? Czy jest to powszechnie stosowane, z kategorycznym wyjaśnieniem, a może z inną nazwą?
Cóż, istnieje ['scanl1Of'] (http://hackage.haskell.org/package/lens-4.13/docs/Control-Lens-Traversal.html#v:scanl1Of). Przy odpowiednim "Traversal" może to wystarczyć. – leftaroundabout
Nie jestem pewien, czy ten rozszerzony 'scanl' powinien przekazać ten sam' init' wszystkim dzieciom, jak to zrobiono powyżej, lub połączyć je tak jak 'fold'. – chi
** chi ** to 'scanl' to' scan :: Traverseable f => (b -> a -> b) -> b -> f a -> f b; scan f z a = evalState (traverse (\ x -> modify (flip f x) >> get) a) z'. – user3237465