I am trying to write a function that accepts a function and two inputs, and returns the argument that maximizes the function. This is the setup I want to use:
max :: Eq a => (a -> Int) -> a -> a -> a
For example, the function should work as follows:
maximize (+3) 5 10 = 10
Because (3+5) < (3+10)
I am thinking I need to do something like this:
maximize :: Eq a => (a -> Int) -> a -> a -> a
maximize f x y = max (f x) (f y)
This approach doesn't seem to be working though. Thank you for any help!
Your problem is that max (f x) (f y) gives back either f x or f y, as opposed to either x or y. You have to compare the former pair of values and then return one of the latter. One way of doing that is using compare and then pattern matching on its result, like this:
-- You don't actually need the `Eq a` constraint here.
maximize :: (a -> Int) -> a -> a -> a
maximize f x y = case compare (f x) (f y) of
-- etc. (I will let you fill in the details.)
One shortcut for writing that is using comparing from Data.Ord, which allows you to replace compare (f x) (f y) with comparing f x y. A further shortcut, suggested above by user2407038, uses maximumBy from Data.List to reduce it all to the one-liner maximumBy (comparing f) [x,y].
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With