【问题标题】:Haskell Tree foldt on Tree with variable membersHaskell Tree foldt on Tree with variable members
【发布时间】:2015-05-20 17:49:21
【问题描述】:

我正在尝试创建自定义数据类型树。定义如下:

一棵树可以定义为一个叶子(由关键字“Leaf”标识)包含一条信息(即它是一个没有子节点),或一个节点(由关键字“Node”标识)使用一条信息,加上一个树列表——列表中的每个元素代表一个以相应子节点为根的子树。请注意,在此定义下,树永远不能为空。 这意味着一棵树可以是:

  • 叶数据;或
  • 节点数据 [data, data, ...] -- 列表中可以有零个或多个树

这是我的代码:

data Tree a = Leaf a | Node a [ Tree a ] deriving (Show)

foldt :: (a -> a -> a) -> Tree a -> a
foldt f (Leaf a)     = a
foldt f (Node a [])  = a
foldt f (Node a [b]) = f a (foldt f b)

它可以编译,但是当我尝试运行时:

let myTree = Node 'A' [Node 'B' [Leaf 'E', Node 'F' [Leaf 'I', Leaf 'J', Leaf 'K']], Node 'C' [Leaf 'G', Leaf 'H'], Leaf 'D']
foldt min myTree

我收到以下错误,而不是预期的输出 'A'

CSC207a4.hs:(6,1)-(8,38): Non-exhaustive patterns in function foldt

我的函数的哪一部分不是详尽的,或者我是否错误地定义了数据类型?

更新:

我可能已经解决了非穷举模式,我现在有了这个,但它声称树没有定义:

数据树 a = 叶 a |节点a[树a]推导(显示)

foldt :: (a -> a -> a) -> Tree a -> a
foldt f (Leaf a)     = a
foldt f (Node a [])  = a
foldt f (Node a [(Tree x)])  = f a (foldt f x)
foldt f (Node a [(Tree x):xs]) = f a (foldt f (f x (foldt f xs)))

【问题讨论】:

  • 您只考虑了 [Tree a] 是 0 个元素或 1 个元素的情况。如果我有Node 1 [Leaf 2, Leaf 3]怎么办?
  • 我想我找到了解决办法,但现在它声称当我尝试使用 Tree 时它不存在。
  • LeafNode 实际上不是关键字——它们是数据构造函数。
  • 那是什么意思?
  • 关键字类似于letifthen 等,内置于语言语法中。数据构造器是您在 Haskell 中从较小的部分构建值的方式。然后,数据构造函数上的模式匹配是您从值中取出较小部分的方法。

标签: haskell recursion tree


【解决方案1】:

您可以通过打开警告从 GHC 获得一些帮助。 “大锤”是-Wall

-- At the very top of the file
{-# OPTIONS_GHC -Wall #-}

噪音较小的方法也可以:

{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}

其中任何一个都会在编译时为您提供您未能匹配的模式的明确列表。

Tree 放在你的模式中不起作用的原因是Tree 是一个type 构造函数(你把它们放在左手 datanewtype 声明的两侧)。只有 data 构造函数(将它们放在 datanewtype 声明的 右手 侧进行的排序)可以在模式中匹配。

【讨论】:

  • 那么,我的问题有什么可能的解决方案?我很难理解它。
  • @Himself12794,是的,您的问题有解决方案!你很快就会明白的。请参阅learnhaskell 获取一些好的资源。
  • @Himself12794,为了简化一点,我建议你首先编写一个折叠列表的版本,然后是二叉树,然后是 data Tree = Node a [Tree a] 定义的树(称为玫瑰树),然后最后是你实际处理的那些奇怪的东西。
  • 我想现在必须这样做。我只是没有得到我目前上课的任何东西的好例子。
  • 我真的没有时间从其他来源学习,而且我没有从我的课程中得到任何有用的东西,这需要我解决这个问题。
【解决方案2】:

我找到了答案。熬了一夜之后,我灵光一现。这里是:

module CSC207a4 where

data Tree a = Leaf a | Node a [ Tree a ] deriving (Show)

foldt :: (a -> a -> a) -> Tree a -> a
foldt _ (Leaf a)    = a
foldt _ (Node a []) = a
foldt f (Node a b)  = f (foldt f x) (foldt f (Node a xs))
    where
        x:xs = b

这通过了所有的测试用例,并回答了我的问题。

【讨论】:

  • 我知道你可以得到它。但是,您应该直接将b 替换为x:xs。这整个练习有点奇怪。这种(非常特殊的)树类型更常见的折叠如下所示:foldTree :: (a -> b) -> (a -> [a] -> b) -> Tree a -> b。你能写那个吗?
  • 感谢您的信任投票,:) 我真的没有时间深入研究,但很高兴知道我解决了其中一个比较困难的问题。
猜你喜欢
  • 2017-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-28
  • 1970-01-01
  • 1970-01-01
  • 2017-07-15
  • 2019-12-18
相关资源
最近更新 更多