如何在 Haskell 函数中对递归数据类型进行递归

Posted

技术标签:

【中文标题】如何在 Haskell 函数中对递归数据类型进行递归【英文标题】:How to do recursion for recursive data type in function in Haskell 【发布时间】:2022-01-06 19:00:42 【问题描述】:

我正在尝试实现 menu 函数,该函数返回来自自定义数据类型 Page 的所有标题

data Page = Text String
         | Title String [Page] deriving(Show)
menu :: Page -> [String]
menu (Text a) = []
menu (Title name content ) = [name]

但我也希望此功能也适用于某些“层次结构”的页面,例如index

index = Title "Home" [
  Title "Welcome!"[
    Text "Hello World!", 
    Title "Lorem"[Text "ipsum"]],
  Title "dolor"[
    Title "no title" [Text "Haskell"],
    Title "Look!" [Text "test"]],
  Title "Finish" [Text "It will be look great"]]

我为此做了一些函数,但我不知道如何开始递归“层次结构”Page

menu :: Page -> [String]
menu (Text a) = []
menu (Title name content ) = [name]

输出是

*Main> menu index
["Home"]

但是我可以列出index 中的所有Title 吗?

非常感谢您的回答!

【问题讨论】:

你有一个页面列表;在上面映射menu,你会得到一个列表列表。连接这些列表,然后将 name 添加到结果中。 【参考方案1】:

一种方法如下:

data Page = Text String
         | Title String [Page] deriving(Show)
menu :: Page -> [String]
menu (Text a) = [a]
menu (Title name content) = name : concatMap menu content

data Page = Text String
         | Title String [Page] deriving(Show)
menu :: Page -> [String]
menu (Text a) = [a]
menu (Title name content) = name : concatMap menu content

一个小测试:

λ> menu index
["Home","Welcome!","Hello World!","Lorem","ipsum","dolor","no title","Haskell","Look!","test","Finish","It will be look great"]

我们正在使用concatMap

由于Text a 是一个叶子,我们将提取的a 返回为[a] 列表中的String

Title name content 有 2 个部分。 name 只是一个字符串,所以我们将它添加到列表中并递归调用menu。但我们不能只使用mapmenu 而不是content,因为内容是Pages 的列表。这意味着我们有一个递归数据类型列表。所以我们使用concatMap,它只是连接列表中每个Page 生成的列表。

如果您想跟踪字符串是Title 还是Text

data Page = Text String
         | Title String [Page] deriving(Show)
menu :: Page -> [String]
menu (Text a) = ["Text " ++ a]
menu (Title name content) = ("Title " ++ name) : concatMap menu content

【讨论】:

以上是关于如何在 Haskell 函数中对递归数据类型进行递归的主要内容,如果未能解决你的问题,请参考以下文章

在 Haskell 中对 3 个参数进行柯里化

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

如何在Haskell中与代数类型进行模式匹配

如何在 Haskell 中进行类型反射

Haskell入门篇九:高阶函数(中)

如何使用haskell类型系统来描述关系,从而防止出现更多错误