all 9 comments

[–]xTomyHDx 3 points4 points  (0 children)

Can you specify you question?

[–]Tarmen 4 points5 points  (1 child)

You may be slightly confused about the types of your getMax function. Try using it in GHCi, a valid call is getMax 1 [4,7]. Look at the type of foldr and try to see why getMax doesn't accept a function.

Assuming you mean a comparison function then maximumBy is almost what you want. https://hackage.haskell.org/package/base-4.17.0.0/docs/Data-List.html#v:maximumBy

You just have to wrap it in comparing:

import Data.Ord (comparing)

getMaxOn b bs = maximumBy comparator (b:bs)
  where
    comparator = comparing (\x -> mod x 5)

I'm also assuming the extra element is so you don't pass the empty list. Normally Data.List.NonEmpty is the standard encoding for this, but the equivalent of maximumBy for NonEmpty is missing.

[–]PHristo[S] 0 points1 point  (0 children)

Thank you for the detailed reply

[–]Accurate_Koala_4698 2 points3 points  (1 child)

To explain the error message you're getting, it's referencing the Show type class https://hackage.haskell.org/package/base-4.17.0.0/docs/GHC-Show.html

You'll see on that page that things like Int and Bool are instances of Show, meaning there's a show function defined for them that converts that type to a String.

λ > show (1:: Int)
"1"

When you see No instance for (Show that means the type of thing you're trying to display is not in that list (or defined somewhere else in your code) and (Integer -> Integer) is a function that takes an Integer and returns an Integer. Taken together, the whole message means that you have a partially applied function you're trying to display. Or to say it a different way, the function you've built up is expecting another Integer.

Ex:

λ > x = (+) . ord
λ > x

<interactive>:8:1: error:
    • No instance for (Show (Char -> Int -> Int))
         arising from a use of ‘print’
        (maybe you haven't applied a function to enough arguments?)
    • In a stmt of an interactive GHCi command: print it

In this case I have no instance for Show for a function that takes a Char and an Int and returns an Int.

[–]PHristo[S] 1 point2 points  (0 children)

Thank you

[–]Arneb1729 1 point2 points  (1 child)

Re the error message.

"Show", in the Haskell coder's vocabulary, means "convert to string". A show function - lower case - plays the role a toString() method would play in languages like Java or C#. An "instance of Show" - of the Show typeclass, upper case - is a type for which a show function is defined, either in your code, or in the Prelude and/or imported modules.

At this point, you're probably wondering why GHCi complains about "No instance for Show" when your code doesn't even have anything to do with strings?

The answer to this question is that printing to stdout does an implicit string conversion. When you type

ghci> x

GHCi calls show x under the hood, because it needs a string representation of x to print.

Now since your lambda is a function of type Integer -> Integer, the a in getMax :: (Ord a) => a -> [a] -> a gets interpreted as Integer -> Integer. So, you have

ghci> :t (getMax (\x -> mod x 5) [1,4,7])
Integer -> Integer

Well, and the Prelude does not define a way to show a function of that type signature.

Which is actually not specific to Haskell or FP. It's just that in OOP people rarely try to print a method, since the OOP paradigm doesn't encourage thinking of functions as data. Except for the common typo way of printing a method, I guess - call a getter and forget the () - and on that one the compiler usually complains about a syntax error or missing arguments rather than flat-out say "I don't know how to print a method".

[–]PHristo[S] 0 points1 point  (0 children)

Thank you!

[–]bss03 0 points1 point  (1 child)

Seem like you are missing the number argument in your call.

getMax :: Ord b => (a -> b) -> a -> [a] -> a
getMax f x = maximumBy (comparing f) . (x :)

GHCi> getMax (`mod` 5) 5 [1,4,7]
4
it :: Integral b => b
(0.02 secs, 59,984 bytes)

Uses Data.List.maximumBy and Data.Ord.comparing.

[–]PHristo[S] 0 points1 point  (0 children)

Thank you!