简体   繁体   中英

Haskell-Custom data types

I need some advice on how to return a list of chapter names that do not contain text blocks (Text) in their type list [Article]

data Article = Text String
             | Section String [Article] deriving (Show)

myArticle :: Article
myArticle = Section "Document" [
                 Section "Introduction" [
                       Text "My intoduction",
                       Section "Notation" [Text "alpha beta gamma"]],
                 Section "Methods" [
                       Section "Functional Programming" [Text "FPR"],
                       Section "Logical Programming" [Text "LPR"]],
                 Section "Results" [Text "All is great"]]
names :: Article -> [String]

Expected output:

names myArticle = ["Document", "Methods"]

I tried the basic functions:

names :: Article -> [String]

Always start by observing the structure of your datatype:

                     Section
                   /        \
                Text        Section
                            /   |  \
                         Text Text  Text

You can see that this is a tree. Thus we start by deconstructing this tree in names:

names :: Article -> [String]
names a = case a of
  Text _ -> []
  Section chptr xs -> []

We only want to return chptr if none of it's childs in the list xs is text. Thus we need a function to know whether something is text:

isText :: Article -> Bool
isText (Text _) = True
isText _ = False

Now looking at names we can use the built-in any:: (a -> Bool) -> [a] -> Bool function to return chptr, if none of it's childs is text:

names :: Article -> [String]
names a = case a of
  Text _ -> []
  Section chptr xs -> 
    (if any isText xs then [] else [chptr]) 

But names only returns the first chapter name. We already concluded this is a tree, and processing these in Haskell is usually done recursively. So we must call names again on our list xs of sections, and add the result to the names we already found:

names :: Article -> [String]
names a = case a of
  Text _ -> []
  Section chptr xs -> 
    (if any isText xs then [] else [chptr]) ++ concatMap names xs 

voila!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM