MackeyRMS / elm-rosetree-path / Tree.Navigate

Additional helpers for a zwilias/elm-rosetree using TreePath

observe

to : Tree.Path.TreePath -> Tree label -> Maybe (Tree label)

Following the TreePath, where do we end?

import Tree exposing (tree)
import Tree.Navigate
import Tree.Path

Tree.singleton "jo"
    |> Tree.Navigate.to Tree.Path.atTrunk
--> Just (Tree.singleton "jo")

tree "jo"
    [ Tree.singleton "ann"
    , tree "mic"
        [ Tree.singleton "igg"
        , Tree.singleton "dee"
        , Tree.singleton "bee"
        ]
    ]
    |> Tree.Navigate.to (Tree.Path.follow [ 1, 2 ])
--> Just (Tree.singleton "bee")

tree "jo"
    [ Tree.singleton "ann"
    , tree "mic"
        [ Tree.singleton "igg"
        , Tree.singleton "dee"
        ]
    ]
    |> Tree.Navigate.to (Tree.Path.follow [ 1, 2 ])
--> Nothing

altering

map : ({ path : Tree.Path.TreePath, label : label } -> mappedLabel) -> Tree label -> Tree mappedLabel

Change every label based on its TreePath and current value.

import Tree exposing (tree)
import Tree.Navigate
import Tree.Path

tree 1
    [ Tree.singleton 2
    , tree 3 [ Tree.singleton 4 ]
    , Tree.singleton 5
    ]
    |> Tree.Navigate.map
        (\n -> ( n.label * 2, n.path ))
--> tree ( 2, Tree.Path.atTrunk )
-->     [ Tree.singleton ( 4, Tree.Path.follow [ 0 ] )
-->     , tree ( 6, Tree.Path.follow [ 1 ] )
-->         [ Tree.singleton ( 8, Tree.Path.follow [ 1, 0 ] ) ]
-->     , Tree.singleton ( 10, Tree.Path.follow [ 2 ] )
-->     ]


tree 0 [ Tree.singleton 1, tree 2 [ Tree.singleton 3 ], Tree.singleton 5 ]
    |> Tree.Navigate.map identity
    |> Tree.flatten
--> [ { label = 0, path = Tree.Path.atTrunk }
--> , { label = 1, path = Tree.Path.follow [ 0 ] }
--> , { label = 2, path = Tree.Path.follow [ 1 ] }
--> , { label = 3, path = Tree.Path.follow [ 1, 0 ] }
--> , { label = 5, path = Tree.Path.follow [ 2 ] }
--> ]

alter : Tree.Path.TreePath -> (Tree a -> Tree a) -> Tree a -> Tree a

Change its sub-tree at a given TreePath based on its current value.

import Tree exposing (tree)
import Tree.Navigate
import Tree.Path

tree "jo"
    [ Tree.singleton "ann"
    , tree "mic"
        [ Tree.singleton "igg"
        , Tree.singleton "dee"
        , Tree.singleton "bee"
        ]
    ]
    |> Tree.Navigate.alter (Tree.Path.follow [ 1, 2 ])
        (Tree.mapLabel String.toUpper)
--> tree "jo"
-->     [ Tree.singleton "ann"
-->     , tree "mic"
-->         [ Tree.singleton "igg"
-->         , Tree.singleton "dee"
-->         , Tree.singleton "BEE"
-->         ]
-->     ]

tree "jo"
    [ Tree.singleton "ann"
    , tree "mic"
        [ Tree.singleton "igg"
        , Tree.singleton "dee"
        ]
    ]
    |> Tree.Navigate.alter (Tree.Path.follow [ 1, 2 ])
        (Tree.mapLabel String.toUpper)
--> tree "jo"
-->     [ Tree.singleton "ann"
-->     , tree "mic"
-->         [ Tree.singleton "igg"
-->         , Tree.singleton "dee"
-->         ]
-->     ]

transform

restructure : ({ path : Tree.Path.TreePath, label : label, children : List folded } -> folded) -> Tree label -> folded

A powerful tree transformation which can be described as "replacing the tree node constructors"

invertTree : Tree label -> Tree label
invertTree =
    Tree.Navigate.restructure (\sub -> tree sub.label (sub.children |> List.reverse))

toPreOrder : Tree label -> List label
toPreOrder =
    Tree.Navigate.restructure (\sub -> sub.label :: (sub.children |> List.concat))

type DifferentTree a
    = DifferentTree a (List (DifferentTree a))

toDifferentTree : Tree label -> DifferentTree label
toDifferentTree =
    Tree.Navigate.restructure (\sub -> DifferentTree sub.label sub.children)

Other names for this pattern are "unwrap", "fold" and "banana" Resources I can recommend:

Additionally, you get the TreePath at each step. Check the readme for how this can be useful.