2

I'm trying to write a function that finds the last element of a list of Ints given that all the Ints are greater than 100. This is the code I have written so far:

isLeast100All :: [Int] -> [Int]
isLeast100All list = filter (>100) list

lastList :: [Integer] -> Integer
lastList list' = case list' of
  isLeast100All list
    | list == []   -> 0
    | list == [x]  -> x
    | list == [x:xs] -> lastList xs

which gives me the error: "Parse error in pattern: isLeast100All"

I feel like there's something simple that I'm missing here but I'm not sure what it is. I'm basing my lastList function off the following definition:

lastList :: [Integer] -> Integer
lastList x = case x of
  [] -> 0
  [x] -> x
  x:xs -> lastList xs
dtmerc
  • 23
  • 3
  • So what should happen here? `lastList` should return last element of `list'` if all it's elements are greater than 100? Or it should return last element of list which is greater than 100? Also I would say that your `case` expression is malformed. – Guru Stron May 25 '22 at 12:43
  • @GuruStron I want it to return the last element of a list that only contains elements greater than 100 – dtmerc May 25 '22 at 12:52
  • And what if list contains elements less or equal than 100? – Guru Stron May 25 '22 at 12:56
  • Sorry I just fixed it now. I want to filter the list to only have elements > 100, then find the last element of that list – dtmerc May 25 '22 at 13:26
  • The check `foo == []` is [a code smell](https://stackoverflow.com/q/57029258/791604). – Daniel Wagner May 25 '22 at 18:09

2 Answers2

0

You need to fix your types and use filter instead of map for isLeast100All:

isLeast100All :: [Integer] -> [Integer]
isLeast100All = filter (> 100)

lastList :: [Integer] -> Integer
lastList list' = case isLeast100All list' of
    []   -> 0 
    xs  -> last xs

Or just:

lastList :: [Integer] -> Integer
lastList l = last $ 0 : filter (> 100) l
Guru Stron
  • 102,774
  • 10
  • 95
  • 132
0

There are a couple of problems with your definition of lastList. You have confused list and list', [x:xs] should be (x:xs), and you're mixing predicate guards and case ... of expression.

Here's one way you can define it using predicate guards:

lastList :: [Integer] -> Integer
lastList list' = myLast $ isLeast100All list'

myLast :: [Integer] -> Integer
myLast list
    | list == [] = 0
    | tail list == [] = head list
    | otherwise = myLast $ tail list

Here's another using case ... of:

lastList :: [Integer] -> Integer
astList list' = case isLeast100All list' of
    [] -> 0
    [x] -> x
    (x:xs) -> lastList xs

This latter one is needlessly inefficient because the filtering function isLeast100All is applied to the entire remaining list at every level of recursion but I aimed to make these as similar to your code as possible.

The answer by Guru Stron gives simpler alternatives.

QuantumWiz
  • 148
  • 9