Home > Enterprise >  Suspceted error in declaration of list of lists, not sure how to correct
Suspceted error in declaration of list of lists, not sure how to correct

Time:02-25

I am attempting to take a list of lists and print the maximum value found amongst all the lists. I have a function I believe should work, but I believe the way I am declaring the values is causing a problem.

nested_max :: [[Int]] -> Int
nested_max [] = minBound::Int
nested_max [[x]] = x
nested_max [[x,xs]]  = nested_helper [[x,xs]]

nested_helper [[x,xs]]= maximum (concat[[x,xs]])

Any help is appreciated.

CodePudding user response:

All patterns except the first one match with a singleton list: a list with one element. In that list you match again with a singleton list (so a list with one element that is a list with one element), and a list with two elements).

But you thus do not match with a list with an arbitrary number of sublists, nor with a list that has as first list a list with zero or more than two elements.

You however do not need to pattern match on the list, you can work with:

nested_max :: [[Int]] -> Int
nested_max = helper . concat
    where helper [] = minBound
          helper xs = maximum xs

We thus first concatenate the list of lists into a single list, then we check if that list is empty, in which case we return minBound, or we return maximum xs which will return the maximum of the elements.

CodePudding user response:

The problem is the declaration [[x,xs]], which is a list, which contains a list of two elements. This is not what you want, as it is not the general case - at some point you need the general case to match everything that you haven't matched yet.

You could try lst:lsts which matches the first element, the head, against lst and the other elements (if any) against lsts - this is the standard technique for recursion. We are not doing recursion here, so we can ignore this.

You could try nlsts which matches the list of lists in one go. Since you are passing one item to nested_helper and concat this seems to be the more natural and correct thing to do.

Thus:

nested_max :: [[Int]] -> Int
nested_max [] = minBound::Int
nested_max [[x]] = x
nested_max nlsts  = nested_helper nlsts

nested_helper nlsts = maximum (concat nlsts)

For completeness, there is a recursive version. This uses the lst:lsts form:

nested_max_new :: [[Int]] -> Int
nested_max_new [[]] = minBound
nested_max_new nlst = maximum (nested_helper_new nlst)

nested_helper_new :: [[Int]] -> [Int]
nested_helper_new [] = []
nested_helper_new (lst:nlst) = (maximum lst) : nested_helper_new nlst

Finally, in practical code we try to use map, filter and reduce - it doesn't much matter which functional language it is. This tends to provide the simplest and most readable code:

nestedMax :: [[Int]] -> Int
nestedMax nlst = maximum (map (\x -> maximum x) nlst)

NB: Like so many of Haskell's base functionality, maximum is a partial function, it doesn't work for all inputs. So you might prefer:

maxList::[Int] -> Int
maxList [] = minBound
maxList lst = maximum lst 
  • Related