I am trying to implement menu
function that returns all titles from custom data type Page
data Page = Text String
| Title String [Page] deriving(Show)
menu :: Page -> [String]
menu (Text a) = []
menu (Title name content ) = [name]
But I want also this function will work also for some "hierarchy" of pages, for example, like in 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"]]
I done some functions for this, but I have no idea how to start recursion for "hierarchy" Page
menu :: Page -> [String]
menu (Text a) = []
menu (Title name content ) = [name]
The output is
*Main> menu index
["Home"]
But can I do list of all Title
in index
?
Thanks a lot in advance for answer!
CodePudding user response:
One way to do it is as follows:
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
A small test:
λ> menu index
["Home","Welcome!","Hello World!","Lorem","ipsum","dolor","no title","Haskell","Look!","test","Finish","It will be look great"]
We are using concatMap
.
Since Text a
is a leaf, we return the extracted a
which is its String
in a list as [a]
.
Title name content
has 2 parts. name
is just a string, so we add it to the list and recursively call menu
. But we can't just map
menu
over content
, since content is a list of Page
s. That means that we have a list of recursive data types. So we use concatMap
that just concatenates the lists that are produced by each Page
in the list.
If you like to keep track of whether a string was a Title
or a 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