Problem using map with list of lists in Haskell
I am using Haskell to solve problem 99 in an euler project where I have to find the maximum result from a list of base exponent pairs.
I came up with this:
prob99 = maximum $ map ((fst)^(snd)) numbers
Where the numbers are in the form:
numbers = [[519432,525806],[632382,518061],[78864,613712]..
Why doesn't it work? Do I need to change the format of numbers? Is there a simple optimization I don't think of as a more efficient exponentiation method?
source to share
Since fst and snd are defined for pairs (types fst :: (a, b) β a and snd :: (a, b) β b). And the second problem is with (fst) ^ (snd), you cannot use a function function.
prob99 = maximum $ map (\xs -> (head xs)^(head (tail xs))) numbers
or
prob99 = maximum $ map (\xs -> (xs !! 0)^(xs !! 1)) numbers
source to share
Give a man a fish and you feed him for a day, teach a man to fish and you will feed him for life.
Jonno, you should learn how to resolve GHC error messages for you, and the undefined
drop method (let's focus on that for now).
ghci> let numbers = [[519432,525806],[632382,518061]]
ghci> -- so far so good..
ghci> let prob99 = maximum $ map ((fst)^(snd)) numbers
<Bam! Some type error>
ghci> -- ok, what could have gone wrong?
ghci> -- I am pretty sure that this part is fine:
ghci> let prob99 = maximum $ map undefined numbers
ghci> -- yes, it is fine
ghci> -- so the culprit must be in the "((fst)^(snd))" part
ghci> let f = ((fst)^(snd))
<Bam! Some type error>
ghci> -- whoa, so this function never makes sense, not just where I used it..
ghci> -- is it doing what I think it is doing? lets get rid of those braces
ghci> let f = fst ^ snd
<Bam! Same type error>
ghci> -- yeah I got my syntax right alright
ghci> -- well, can I exponent fst?
ghci> let f = fst ^ undefined
No instance for (Num ((a, b) -> a))
arising from a use of '^' at <interactive>:1:8-22
Possible fix: add an instance declaration for (Num ((a, b) -> a))
In the expression: fst ^ undefined
In the definition of 'f': f = fst ^ undefined
ghci> -- duh, fst is not a Num
ghci> -- this is what I wanted:
ghci> let f x = fst x ^ snd x
ghci> -- now lets try it
ghci> let prob99 = maximum $ map f numbers
<Bam! Some type error>
ghci> -- still does not work
ghci> -- but at least f makes some sense now
ghci> :t f
f :: (Num a, Integral b) => (a, b) -> a
ghci> -- lets find an example input for it
ghci> head numbers
[519432,525806]
ghci> :t head numbers
head numbers :: [Integer]
ghci> -- oh, so it is a list of two integers and not a tuple!
ghci> let f [a, b] = a ^ b
ghci> let prob99 = maximum $ map f numbers
ghci> -- no error?
ghci> -- finally I got the types right!
source to share
What doesn't work is your sequence of program types. You are trying to apply a function (^)
, a simplified type Int -> Int -> Int
, to type arguments (a,a) -> a
(not Int).
The easiest way is probably to directly create a list of pairs instead of a list of lists. Then you can (almost) directly attach the function (^) to them by first discarding it.
numbers = [(519432,525806),(632382,518061),(78864,613712)...
prob99 = maximum $ map (uncurry (^)) numbers
If you get stuck with your sublists, you can map them directly to templates by improving Matajon's solution a bit:
prob99 = maximum $ map (\[x,y] -> x^y) numbers
Or, if you are fully using the no-reference style, you can effectively use operators in Control.Arrow
. (which doesn't help much in this case, as far as verbosity is concerned)
prob99 = maximum $ map ((!!0) &&& (!!1) >>> uncurry (^)) numbers
source to share