profold/src/Profold/LineNode.hs
2020-03-01 09:48:27 +00:00

40 lines
1.1 KiB
Haskell

module Profold.LineNode
( LineNode(..)
, newLineNode
, Path
, flatten
, modify
) where
import qualified Data.Text as T
import qualified Data.Vector as V
data LineNode = LineNode
{ lineText :: T.Text
, lineChildren :: V.Vector LineNode
, lineFolded :: Bool
} deriving (Show)
newLineNode :: T.Text -> [LineNode] -> LineNode
newLineNode text children = LineNode text (V.fromList children) True
type Path = [Int]
flatten :: LineNode -> V.Vector (Path, LineNode)
flatten ln
| lineFolded ln = V.singleton ([], ln)
| otherwise =
V.cons ([], ln) $
V.concat $ V.toList $ V.imap flattenChild $ lineChildren ln
where
flattenChild :: Int -> LineNode -> V.Vector (Path, LineNode)
flattenChild i c = V.map (\(is, n) -> (i : is, n)) $ flatten c
modifyAtIndex :: Int -> (a -> a) -> V.Vector a -> V.Vector a
-- Yes, this function looks ugly, but it's short enough that I don't care.
modifyAtIndex i f v = maybe v (\a -> v V.// [(i, f a)]) (v V.!? i)
modify :: (LineNode -> LineNode) -> Path -> LineNode -> LineNode
modify f [] ln = f ln
modify f (i:is) ln =
ln {lineChildren = modifyAtIndex i (modify f is) $ lineChildren ln}