1

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!

1
  • 1
    You have a list of pages; map menu over that, and you'll get a list of lists. Concatenate those lists, then prepend name to the result. Commented Nov 30, 2021 at 0:52

1 Answer 1

1

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 Pages. 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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.