在 haskell -> TRIE 中使用自定义递归数据类型

Posted

技术标签:

【中文标题】在 haskell -> TRIE 中使用自定义递归数据类型【英文标题】:Using custom recursive data type in haskell -> TRIE 【发布时间】:2021-12-28 06:23:13 【问题描述】:

我正在学习 Haskell,但遇到了一个似乎很难的问题。

我有 Trie 的自定义递归数据类型。

data Trie keytype valuetype = TNode (Maybe valuetype) [Edge keytype valuetype]
            deriving (Show, Eq)

type Edge e a = (e, Trie e a)

我正在尝试实现与它一起使用的功能。我发现如何遍历它不正确的顺序。

isTrieValid :: Ord e => Trie e a -> [e]
isTrieValid (TNode _ []) = []
isTrieValid (TNode _ ((edge, TNode maybe innerlist):children)) =  edge : printChildren innerlist  ++ printChildren children
       where  
              printChildren :: Ord e => [Edge e valuetype] -> [e]
              printChildren [] = []
              printChildren ((edge_name, TNode _ innerlist):xs) =edge_name : printChildren innerlist ++ printChildren xs

例如。对于以下特里,返回所有“键”(边缘名称)->“abbce”

trie1 = TNode (Just 42) [('a', TNode (Just 16) []),
         ('b', TNode Nothing
               [('b', TNode (Just 1) []),
                ('c', TNode (Just 5) []),
                ('e', TNode (Just 2) [])
               ])
        ]

现在我正在尝试创建基于“键”查找元素的函数,如下所示:

trieLookup :: Ord e => [e] -> Trie e a -> Maybe a

但我看到了两个问题。首先,如果我用递归遍历 Trie,我不确定如何处理第一个元素。因为第一个元素没有“键”,我应该返回什么?我认为空字符串会起作用,但我希望将整个“Ord”类型类用于键,这样会引发类型错误。

我尝试创建的下一个函数将检查 Trie 有效性。

isTrieValid :: Ord e => Trie e a -> Bool

我的理解是,Trie 必须具备这种品质才能被认为是有效的。

当前元素之后的所有元素都按第一个元素排序(按Ord e排序) 没有两个后继者拥有相同的密钥

因此,如果根节点有效并且所有子树/subtriee(不确定如何编写)也有效,则整个 TRIE 有效。

我想创建一个函数来检查一个节点的有效性,然后使用上面的函数在所有节点上复制它,但我失败了。

感谢您的帮助。

【问题讨论】:

Mod note:不要仅仅因为它是一个积极的家庭作业而标记这个问题。 We allow homework questions,只要他们是properly asked,,这个问题似乎是(至少对我来说是一个非中小企业)。这是一个家庭作业问题不是一个密切的原因。我们还don't care if it's part of anything active或违反荣誉守则。 也就是说,如果这被证明是由于其他原因而可以关闭的,请继续使用适当的标志来标记相关原因,但它是一个积极的家庭作业不是这样的原因。 Abdul,请随意忽略这些 cmets。您在这里没有做错任何事情,这些 cmets 不是为了解决您的行为 明确地说,“没有做错任何事”有点过于宽泛——我们不能肯定地说。 Abdul 没有违反 Stack Overflow 规则或政策,但根据学校政策,他可能仍然做错了什么。如前所述,Stack Overflow 无法强制执行这些,因此问题确实是这里的主题,但在更广泛的意义上它可能仍然是“错误的”。 【参考方案1】:

我建议更改您的 Trie 类型。 isTreeValid 的所有属性都可以通过使用Data.Map k v 而不是[Edge k v] 轻松维护。

我真的不明白你在用trieLookup 谈论什么问题。看起来很简单,如果输入键 ([e]) 为空,则返回根处的值,否则进一步下降到树中。什么时候会出现如何治疗根的问题?如果您需要有关该功能的帮助,请附上您解决该问题的尝试并描述问题所在或需要改进的地方。

【讨论】:

我很想改变它,但我不能。这就是任务。 (我在高中) trieLookup 的问题在于,为了有效地做到这一点,我必须检查钥匙,这样我就不会去那些不可能是我正在寻找的价值的分支。所以对于 TRIE,我上面的键“bb”应该返回 1。所以我需要将 b 与 a 和 b 进行比较,发现 a 是 something 并忽略整个分支。我来自python,所以haskell与众不同......如果问题看起来微不足道,我很抱歉。我只是没有看到它。我可以比较字符串,但是当我在控制台中尝试它时,它并没有做我需要做的事情。

以上是关于在 haskell -> TRIE 中使用自定义递归数据类型的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Haskell 中访问没有记录语法的自定义数据类型的字段?

在 Haskell 中使用 Logic Monad

初识Haskell 五:自定义数据类型和类型类

haskell简明入门

是否有类似于 Vector 和其他语言的 Haskell Repa 切片函数的使用?

为自定义对象 oneAPI 创建数据缓冲区时遇到问题