【问题标题】:Attempting to flatten a tree in Haskell using in-order traversal尝试使用中序遍历在 Haskell 中展平一棵树
【发布时间】:2018-09-21 20:45:09
【问题描述】:

尝试使用给定的折叠函数将树展平为列表。

treeFold :: (b -> a -> b -> b) -> b -> Tree a -> b
treeFold _ b Leaf         = b
treeFold f b (Node lt x rt) = f (treeFold f b lt) x (treeFold f b rt)

到目前为止,这是我尝试过的:

treeToList :: Tree a -> [a]
treeToList = treeFold (\xs x ys -> xs ++ x : ys) (\x -> [x])

出于某种原因,我不知道该怎么做? 感觉好像有一些关于 Haskell 的事情我还没有完全进入我的脑海。任何帮助以及如何解决它都会受到赞赏。 谢谢!

编辑:

我意识到我在这里使用的类型签名几乎是荒谬的。在 treeFold 的类型签名中,根据我的想法,第二个参数 (b) 可能是一个列表,因为它在这种情况下以某种方式充当累加器。这将使第三个参数(树 a)成为等式左侧参数的某个版本。函数中的两个参数必须是节点中的左右子树。第三个参数只是节点的值。在函数中,我需要按通常的顺序组合左树、右树和值,但我尝试的所有不同变体都有一些问题

【问题讨论】:

  • (\x -> [x]) 在这里做什么?

标签: haskell functional-programming binary-tree


【解决方案1】:

类型必须适合:

treeFold ::           ( b -> a -> b -> b              ) -> b -> Tree a -> b

treeToList = treeFold (\xs   x    ys -> xs ++ (x : ys))    z
-------------------------------------------------------------------
                        b    a    b     b      a   b       b
                                              --------
                                              b

由于xys参与同一个:,所以它们的类型必须兼容:

(:) ::   a  -> [a]  ->  [a]
x   ::   a
ys  ::          b
-------------------
              b ~ [a]

所以我们有

treeFold ::           ( [a] -> a -> [a] -> [a]           ) -> [a] -> Tree a->[a]

treeToList = treeFold (\ xs    x    ys  -> xs ++ (x : ys))     z
-------------------------------------------------------------------
                         [a]   a    [a]    [a]    a   [a]     [a]
                                                 --------
                                                 [a]

结论:最后一个参数z的类型必须是[a]

这个论点是什么意思?与折叠一样,数据类型定义中的每个“变体”都有一个对应于折叠函数的参数。

您的(缺少的)数据类型定义是:

data Tree a = Node (Tree a)    a   (Tree a)       | Leaf

折叠的类型是

treeFold ::   (         b  ->  a  ->  b  -> b )   ->  b     -> Tree a -> b

对应于

的“递归结果-持有类型”
data TreeF a r = NodeF  r      a      r           | LeafF

因此z 是“将每个Leaf 转换为的值”。

最自然的选择就是[]。实际上,这是唯一的选择,因为我们对a(在[a])类型一无所知。

【讨论】:

  • 啊,这很有道理。我想我仍然刚刚开始思考 Haskell 中函数的应用以及使用提供的类型来推理参数的方法。谢谢!
  • 最主要的是,不要害怕类型!类型是你的朋友! (真的,不像在“火星袭击!”电影中那样:))。 --- 至于应用,主要是这样的:f :: a -> b -> c -> d,我们有f (x::a) :: b -> c -> df (x::a) (y::b) :: c -> df (x::a) (y::b) (z::c) :: d。就是这样!
【解决方案2】:

treeFold 的类型是

treeFold :: (b -> a -> b -> b) -> b -> Tree a -> b

您想要返回一个值列表,[a]

因此结果类型b必须等于[a],给我们一个专门的类型签名

treeFold :: ([a] -> a -> [a] -> [a]) -> [a] -> Tree a -> [a]

请注意,第二个参数的类型为 [a]

你传递的是什么值?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-26
    • 2020-12-06
    • 2018-01-21
    • 1970-01-01
    • 1970-01-01
    • 2020-02-10
    • 2014-11-01
    相关资源
    最近更新 更多