【问题标题】:finding sum of tree to list using haskell使用haskell查找要列出的树的总和
【发布时间】:2015-11-20 21:12:58
【问题描述】:

我在向程序提供输入时尝试使用 id 函数应用 sum。但我在下面。非常感谢任何指导。

data Tree a = Leaf a | Node (Tree a) a (Tree a) deriving (Eq, Show)
reduce_tree :: Tree a -> (a -> b) -> (b -> a -> b -> b) -> b
reduce_tree (Leaf v) = [v]
reduce_tree (Node left root right) = reduce_tree left ++ [root] ++   reduce_tree right

输入如下:

ghci> reduce_tree (VNode (VLeaf 1) 2 (VNode (VLeaf 3) 4 (VLeaf 5)))
                   id sum
                   where sum t1 v t2 = t1 + v + t2
15

【问题讨论】:

  • 我不明白你的问题,看起来它正在按预期工作......
  • @luqui:我想对树进行求和以使用以下函数类型列出但我不明白,reduce_tree :: Tree a -> (a -> b) -> (b - > a -> b -> b) -> b
  • @luqui :使用以下函数类型,我正在尝试对树进行总和以列出 reduce_tree :: Tree a -> (a -> b) -> (b -> a -> b - > b) -> b

标签: haskell


【解决方案1】:

由于我不完全理解你的问题,这里有一些观察:

  • reduce_tree 的类型签名表明它应该有比你给它更多的参数。

    如果f 是一个将a 类型的值映射到b 类型的值的函数,而g 似乎是三个参数的累加函数(尽管我不确定为什么两个是不够),那么

    reduce_tree :: Tree a -> (a -> b) -> (b -> a -> b -> b) -> b
    reduce_tree (Leaf v) f g = ...
    reduce_tree (Node left v right) f g = ...
    
  • 如果reduce_tree 实际上是一个reduce 函数,而不是简单地将树扁平化为列表的函数,那么您可以从Data.Foldable 中汲取灵感。

    data Tree a = Leaf a | Node (Tree a) a (Tree a) deriving (Show, Eq)
    
    treefold :: (a -> b -> b) -> b -> Tree a -> b
    treefold f acc (Leaf x) = f x acc
    treefold f acc1 (Node left x right) =
      let acc2 = treefold f acc1 right
          acc3 = f x acc2
          acc4 = treefold f acc3 left
      in acc4
    

    使用这样的函数,您可以对树的元素进行展平或求和:

    flattenTree :: Tree a -> [a]
    flattenTree tree = treefold (:) [] tree
    
    sumTree :: Num a => Tree a -> a
    sumTree tree = treefold (+) 0 tree
    
  • 当您说“使用 id 函数应用求和”时唯一响起的铃声是您可能希望使用延续。这已经在例如Haskell: tail recursion version of depth of binary tree 和简洁的 Tail-recursion on trees(标准 ML)。 Haskell 等价物是:

    treefold :: (a -> b -> b) -> b -> Tree a -> b
    treefold f acc tree = tf f acc tree id
      where
        tf f acc (Leaf x) k = k (f x acc)
        tf f acc (Node left x right) old_k = tf f left acc new_k
          where
            new_k = \acc -> tf f right (f x acc) old_k
    

    现在sumTree 可以以与以前完全相同的方式定义,除了它将使用折叠以及恒等函数作为初始延续。或者,如果您想自己使用函数 id 提供遍历函数,则可以将辅助函数 tf 提取到顶层。

【讨论】:

  • 下面是你告诉我找到树代码总和的方法:data Tree a = Leaf a |节点 (Tree a) a (Tree a) 导出 (Show, Eq) treefold :: (a -> b -> b) -> b -> Tree a -> b treefold f acc (Leaf x) = f x acc treefold f acc1 (Node left x right) = let acc2 = treefold f acc1 right acc3 = f x acc2 acc4 = treefold f acc3 left in acc4 sumTree :: Num a => Tree a -> a sumTree tree = treefold (+) 0 tree跨度>
  • ghci> sumTree (Node (Leaf 1) 2 (Node (Leaf 3) 4 (Leaf 5))) 15
  • 但我怎样才能在运行时找到总和,如下所示:数据树 a = 叶 a |节点 (Tree a) a (Tree a) 导出 (Show, Eq) treefold :: (a -> b -> b) -> b -> Tree a -> b treefold f acc (Leaf x) = f x acc treefold f acc1 (Node left x right) = let acc2 = treefold f acc1 right acc3 = f x acc2 acc4 = treefold f acc3 left in acc4 flattenTree :: Tree a -> [a] flattenTree tree = treefold (:) [] tree
  • ghci> flattenTree (Node (Leaf 1) 2 (Node (Leaf 3) 4 (Leaf 5)))id sum where sum t1 v t2 = t1 + v + t2 then 输出:15跨度>
【解决方案2】:

哦,如果我理解正确的话,我想你只是想把你的例子输入到 ghci 中。我建议将复杂性放在文件中:

sum_tree :: Tree Int -> Int
sum_tree t = reduce_tree t id sum
    where sum t1 v t2 = t1 + v + t2

然后在 ghci 中,加载定义 sum_treereduce_tree 的文件后,

ghci> sum_tree (VNode (VLeaf 1) 2 (VNode (VLeaf 3) 4 (VLeaf 5))

如果您必须在 ghci 中完成所有操作,请注意通常不能在 ghci 中使用 where,因为 where 仅用于定义中。请改用let ... in

ghci> let sum t1 v t2 = t1 + v + t2 in reduce_tree (VNode (VLeaf 1) 2 (VNode (VLeaf 3) 4 (VLeaf 5))) id sum

如果你因为某种原因不想使用 let,你可以使用 lambda:

ghci> reduce_tree (VNode (VLeaf 1) 2 (VLeaf 3)) id (\t1 v t2 -> t1 + v + t2)

我是否正确理解了您的问题?

【讨论】:

  • 感谢您的回复.. 实际上我想在 ghci 本身中给出标识函数和求和函数而不使用 let... 例如:ghci> reduce_tree (Node (Leaf 1) 2 (Node (Leaf 3) 4 (Leaf 5))) id sum where sum t1 v t2 = t1+v+t2 then output is 15
  • 嗯,好的...我用另一个建议编辑了我的答案。你不能在 ghci 中使用where
  • :使用以下函数类型,我正在尝试对树进行总和以列出 reduce_tree :: Tree a -> (a -> b) -> (b -> a -> b -> b ) -> b
  • 哦,当然,reduce_tree 错了,我没注意到!查看其他答案。
  • 你能用我提到的函数类型解释清楚吗..我很困惑
猜你喜欢
  • 2015-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-28
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 2016-04-02
相关资源
最近更新 更多