简体   繁体   中英

Get parent node of the node in a rose tree

I am trying to get the parent node of the node in a rose tree using following code:

{-# LANGUAGE DeriveAnyClass    #-}
{-# LANGUAGE DeriveFunctor     #-}
{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}

module Main where

import GHC.Generics (Generic)

data RoseTree a = RoseTree { value :: a, children :: [RoseTree a]}
                   deriving (Show, Generic, Functor)

type Timestamp = Integer

type Tree = RoseTree Timestamp 

getParentNode :: Timestamp -> Tree -> Maybe Timestamp 
getParentNode node tree@(RoseTree _ []) = Nothing
getParentNode node tree@(RoseTree rootNode (x:xs)) =
  if node == value x then Just rootNode else case getParentNode node x of 
    Nothing -> case getParentNodeForList node (children x) of 
      Nothing -> getParentNodeForList node xs
      Just parent -> Just parent
    Just parent -> Just parent 

getParentNodeForList :: Timestamp -> [Tree]-> Maybe Timestamp
getParentNodeForList node [] = Nothing
getParentNodeForList node (x:xs) = case getParentNode node x of 
  Nothing -> case getParentNodeForList node (children x) of 
    Nothing -> getParentNodeForList node xs
    Just parent -> Just parent
  Just parent -> Just parent 


main :: IO ()
main = do
  let tree = RoseTree 1623839394 [RoseTree 1623839395 [], RoseTree 1623839396 [], RoseTree 1623839397 []]
  putStrLn $ show $ getParentNode 1623839397 tree

The output is Nothing for this case. I do not understand why. I covered all possible cases of traversing in getParentNode and getParentNodeForList (at least it seems so, it doesn't work apparently).

Any help is appreciated.

I think the problem is that getParentNode should recurse on getParentNode node (RoseTree rootNode xs) , so the whole function would become:

getParentNode :: Timestamp -> Tree -> Maybe Timestamp 
getParentNode node tree@(RoseTree _ []) = Nothing
getParentNode node tree@(RoseTree rootNode (x:xs)) =
  if node == value x then Just rootNode else case getParentNode node x of 
    Nothing -> case getParentNodeForList node (children x) of 
      Nothing -> getParentNode node (RoseTree rootNode xs)
      Just parent -> Just parent
    Just parent -> Just parent 

Personally, I would make use of asum to write it more succinctly:

getParentNode node (RoseTree x xs)
  | node `elem` map value xs = pure x
  | otherwise = asum (map (getParentNode node) xs)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM