在树上映射

ili*_*ats 2 tree dictionary haskell fold

我是新来的Haskell和实践我一直在执行一组函数(map,length使用等)foldrfoldl.现在我想搬到树上!

我的树数据结构:

data Tree a = Node a [Tree a] deriving (Show) 
Run Code Online (Sandbox Code Playgroud)

我编写了一个Haskell函数来折叠树:

treeFold :: (b->a->b) -> b -> Tree a -> b
treeFold f s (Node a []) = f s a
treeFold f s (Node a xs) = foldl f (f s a) (dFSList xs)
Run Code Online (Sandbox Code Playgroud)

其中dFSList是树中所有节点的列表.所以做以下事情:

treeFold (+) 0 (Node 1 [Node 2 [], Node 3 []])
Run Code Online (Sandbox Code Playgroud)

返回6.很酷.

现在我想写一个Haskell函数来映射树,但我想用我的treeFold函数来做它.这是我到目前为止:

treeMap f (Node a []) = (Node (f a) [])
treeMap f (Node a (x:xs)) = (Node (f a) (a list involving foldTree somehow??))
Run Code Online (Sandbox Code Playgroud)

我该如何完成我的treeMap功能?我希望能够做到

treeMap (+1) (Node 1 [Node 2 [], Node 3 []])
Run Code Online (Sandbox Code Playgroud)

它应该回来

(Node 2 [Node 3 [], Node 4 []])
Run Code Online (Sandbox Code Playgroud)

dfe*_*uer 6

拆分树木的方法通常是不同的折叠(通常称为某种类别 - 理论原因我不知道的变形).你有data Tree a = Node a [Tree a],所以要把它分开,你做

cat :: (a -> [b] -> b) -> Tree a -> b
cat f (Node root children) = f root (map (cat f) children)
Run Code Online (Sandbox Code Playgroud)

Hokay?所以现在(使用标准Functor类而不是专用类treeMap),

instance Functor Tree where
  fmap f = cat (Node . f)
Run Code Online (Sandbox Code Playgroud)

你也可以写这样的线性折叠.你treeFold困惑我,但你可以写,例如,

instance Foldable Tree where
  foldMap f = cat go where
    go root children = f root `mappend` fold children
Run Code Online (Sandbox Code Playgroud)

更强大,

instance Traversable Tree where
  traverse f = cat go where
    go root children = Node <$> f root <*> sequenceA children
Run Code Online (Sandbox Code Playgroud)

  • 我相信"catamorphism"一词来自同一个(希腊语,我猜)前缀`cata -`,就像'灾难'一样,意思是"破坏,拆开",如上所述."态射"意味着变形,变形.因此,"catamorphism"只是一种"分裂的转变". (3认同)

Cir*_*dec 5

您无需treeFold编写类似的内容treeMap

treeMap f (Node a xs) = Node (f a) (map (treeMap f) xs)
Run Code Online (Sandbox Code Playgroud)

与相同想法对应的基类是FoldableFunctor。基础上的一切都Foldable已经是Functor; 能够treeMap独立于进行定义是很自然的treeFold

  • 我认为您无法定义“ treeFold”。当您在分支上调用`dFSList`时,它将丢失所有树结构。 (4认同)