Created
November 4, 2017 02:25
-
-
Save snowmantw/f566ba25d3579b23205bcaffb806ea14 to your computer and use it in GitHub Desktop.
List to "Tree" in State Monad
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module StateTree ( buildTree ) where | |
import Prelude hiding (lookup) | |
import Control.Monad.State | |
import Data.Map (Map, insert, insertWith, empty, lookup) | |
data Item = Item { | |
sId :: String, | |
pId :: String, | |
value :: [Char], | |
children :: [String] | |
} deriving (Show) | |
list :: [] Item | |
list = [ Item { sId="1", pId="0", value="1", children=[] } | |
, Item { sId="1-1", pId="1", value="1-1", children=[] } | |
, Item { sId="1-2", pId="1", value="1-2", children=[] } | |
, Item { sId="2", pId="0", value="2", children=[] } | |
, Item { sId="2-1", pId="2", value="2-1", children=[] } | |
, Item { sId="2-2", pId="2", value="2-2", children=[] } | |
] | |
type Table = Map String Item | |
root = Item { sId="0", pId="-1", value="root node", children=[] } | |
-- Make "state lines" for each Item in the list. | |
buildStatement :: Item -> State Table () | |
buildStatement item = | |
state $ \tree -> ((), (mergeNode tree item)) | |
-- insert the item into the map and update the children if pId matches | |
mergeNode :: Table -> Item -> Table | |
mergeNode tree item = | |
case lookup (pId item) tree of | |
Just treeItem -> insert (sId item) item parentUpdated | |
Nothing -> insert (sId item) item tree -- top root | |
where | |
parentUpdated = insertWith mergeToParent (pId item) item tree -- -> map updated | |
mergeToParent child parent = parent { children = children parent ++ [sId child] } | |
statements :: [] Item -> State Table () | |
statements items = | |
foldl folder initStatement items | |
where initStatement = buildStatement root | |
folder sts item = sts >>= (\_ -> buildStatement item) | |
buildTree :: ((), Table) | |
buildTree = runState (statements list) empty |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment