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]
CodePudding user response:
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 listxs
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!