簡體   English   中英

Haskell 中兩棵樹的聯合

[英]Union of two trees in Haskell

我正在努力在 haskell 中為這個問題的域建模。

我知道如何用過程語言解決這個問題(使用循環,這很容易),但似乎無法弄清楚我將如何在 Haskell 中做到這一點。

我想合並(聯合) RoseDirTree

data RoseDirTree
      = File Text Int
      | Folder Text [RoseDirTree]
      deriving (Show, Eq, Ord)

-- | Merges two dir trees
-- If file names are same, prefers the right hands side.
mergeDirTree :: RoseDirTree -> RoseDirTree -> RoseDirTree
mergeDirTree = undefined

這是一個示例案例:

archivesFromS3 :: RoseDirTree
archivesFromS3 = Folder "/"
      [ Folder "2011"
            [ File "jan.dump" 0
            , File "feb.dump" 0
            ]
      , Folder "2012"
            [ File "jan.dump" 0
            ]
      ]

archivesFromLocal :: RoseDirTree
archivesFromLocal = Folder "/"
      [ Folder "2011"
            [ File "jan.dump" 1
            , File "march.dump" 1
            ]
      , Folder "2019"
            [ File "jan.dump" 1
            ]
      ]

-- | archivesFromS3 `mergeDirTree` archivesFromLocal
expectedMerged :: RoseDirTree
expectedMerged = Folder "/"
      [ Folder "2011"
            [ File "jan.dump" 1
            , File "feb.dump" 0
            , File "march.dump" 1
            ]
      , Folder "2012"
            [ File "jan.dump" 0
            ]
      , Folder "2019"
            [ File "jan.dump" 1]
      ]

從更多樹問題的角度來看,我最初的想法是結構必須采用以下形式:

mergeTree :: RoseDirTree -> RoseDirTree -> RoseDirTree
mergeTree (File lhsName idl) (File rhsName idr) = 
      if lhsName == rhsName 
      then File rhsName idr 
      else error "can't merge two different file"
mergeTree (Folder lhsName childl) (Folder rhsName childr) = 
      if lhsName == rhsName 
      then Folder rhsName (childl <> childr) 
      else error "can't merge two different folder"
mergeTree _ _ = error "cannot merge file and folder"

但顯然,這種方法:

  1. 不處理文件夾嵌套同名文件夾的情況。

我真的不知道下一步該去哪里。 任何指針表示贊賞。

有問題的部分是childl <> childr 相反,定義一個新函數:

mergeChildren :: [RoseDirTree] -> [RoseDirTree] -> [RoseDirTree]
mergeChildren = undefined

這個函數應該在某個時候調用mergeTree函數。

要考慮的事情是您是否可以假設輸入文件和文件夾名稱已排序。 如果它們已排序,您將能夠以更簡單的方式實現它。 如果您被允許使用該功能,您也可以考慮使用Data.List.sortOn自己對它們進行排序。

如果輸入是排序的,那么這個函數在結構上可以類似於合並排序的合並,例如 Redu 的這個

 merge :: Ord a => [a] -> [a] -> [a] merge [] ys = ys merge xs [] = xs merge (x:xs) (y:ys) | x < y = x:merge xs (y:ys) | otherwise = y:merge (x:xs) ys

不同之處在於您需要不同的比較功能,如果文件夾或文件相等,則需要執行不同的操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM