0

I am working on a practice quiz and one of the questions makes you work with

data Person = MakePerson String Int Float 

where String is the name, Int is the age, Float is the height. I must create a function that takes in a list of persons and returns the oldest person (know strict rules on if there are n oldest people, just pick one of them. I wrote this

oldest :: [Person] -> String
oldest [] = error("Empty list")
oldest ((MakePerson a b c):(MakePerson d e f):g)
    | (b >= e) && (g == []) = a
    | (b >= e) = oldest (MakePerson a b c):g
    | (b < e) && (g == []) = d
    | otherwise = oldest (MakePerson d e f):g

However, I am getting a parse error. I don't know how to create this function without having this double pattern since I need to always compare b and e and I have no other way of accessing their ages. How would I be able to write out this pattern for my parameters?

Parse Error in pattern: oldest oldest (MakePerson a b c):(MakePerson d e f):g

4
  • 3
    Post the real code and the full error. Commented Mar 4, 2018 at 22:08
  • Looks like you might just be missing an equals sign after the second line of oldest. Hard to tell without looking at the full code though. Commented Mar 4, 2018 at 22:11
  • 2
    What line # is the parse error occurring on? Commented Mar 4, 2018 at 22:21
  • I only ask because the error message seems to refer to something that isn't found on the code sample you pasted. Commented Mar 4, 2018 at 22:42

3 Answers 3

3

One of the simpler things to do is to define a function that compares two people by age, then use Data.List.maximumBy to get the oldest.

compareByAge :: Person -> Person -> Ordering
compareByAge (MakePerson _ a1 _) (MakePerson _ a2 _) = compare a1 a2

getName :: Person -> String
getName (MakePerson name _ _) = name

oldest :: [Person] -> String
oldest people = (getName . maximumBy compareByAge) people
-- or just oldest =  getName . maximumBy compareByAge

Try to avoid explicit recursive functions where possible, as there is often a predefined function available that abstracts the necessary recursion.

Sign up to request clarification or add additional context in comments.

Comments

3

Record syntax will make your life easier. Checkout the relevant LYAH chapter.

import Data.List(maximumBy)
import Data.Function(on)

data Person = MakePerson {getName :: String, getAge :: Int, getHeight :: Float}
oldest = getName . maximumBy (compare `on` getHeight)

Then:

Prelude Data.List> l = [(MakePerson "Alice" 30 5.90), (MakePerson "Bob" 40 5.55), (MakePerson "Claire" 25 6.05)]
Prelude Data.List> oldest l
"Claire"

Edit:

Updated the comparison function per @JonPurdy's comment.

1 Comment

\p1 p1 -> compare (getHeight p1) (getHeight p2) can also be written as comparing getHeight (comparing from Data.Ord) = compare `on` getHeight (on from Data.Function)
2

I assume your strategy is to compare the first two elements of the list and then recurse on the rest of the list. That strategy doesn't work. Take for example the following list (I will only be writing ages as the elements of the list to simplify things):

23:25:21

If you pattern match this list, you'll get the second case, where you take 23:25:g, where g is the rest of the list. You compare 23 and 25, you see that 25 is the older one, and then compare that to the oldest one of the rest of the list, g. But g now only has one element. It's not an empty list, and it's not a list with two elements of type Person. So the program will fail.

Instead, you have to approach this in a simpler, more pure recursive manner. If the list is empty, raise and error. If the list is of just 1 Person, return that Person's age, since they are the oldest by default. If the list is anything else, compare the head of the list's age to the oldest person of the rest of the list. This way, the function will pick off the PersonS one by one, and compare them to get the oldest one.

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.