Skip to content

Instantly share code, notes, and snippets.

@edsko
Last active July 26, 2019 11:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save edsko/4105491c18d005c0e734ab2e8063196f to your computer and use it in GitHub Desktop.
Save edsko/4105491c18d005c0e734ab2e8063196f to your computer and use it in GitHub Desktop.
-- | Recover tree structure from linearized form
--
-- Suppose we have a list of strings
--
-- > A
-- > B
-- > C
-- > D
-- > E
-- > F
--
-- with identation indicating nesting. We want to recover the tree structure
-- from this linearized form.
recoverTree :: forall a.
(a -> a -> Bool) -- Comparing nesting depth
-> [a]
-> (Tree a, [a])
recoverTree nestedBelow = \case
[] -> error "recoverTree: empty list"
x:xs -> let (children, xs') = parseChildrenOf x xs
in (Tree.Node x children, xs')
where
tryParseChildOf :: a -> [a] -> Maybe (Tree a, [a])
tryParseChildOf _ [] = Nothing
tryParseChildOf parent (x:xs) =
if x `nestedBelow` parent
then let (grandchildren, xs') = parseChildrenOf x xs
in Just (Tree.Node x grandchildren, xs')
else Nothing
parseChildrenOf :: a -> [a] -> ([Tree a], [a])
parseChildrenOf parent xs =
case tryParseChildOf parent xs of
Nothing -> ([], xs)
Just (child, xs') -> first (child:) $ parseChildrenOf parent xs'
_exampleLinear :: [String]
_exampleLinear = [
"A"
, " B"
, " C"
, " D"
, " E"
, " F"
]
_exampleTree :: Tree String
_exampleTree = fst $ recoverTree ((>) `on` depth) _exampleLinear
where
depth :: String -> Int
depth = length . takeWhile (== ' ')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment