使用带有Haskell中列表列表的映射的问题

时间:2009-09-30 07:40:13

标签: haskell dictionary exponentiation

我正在使用Haskell解决euler项目中的问题99,我必须从基本指数对列表中找到最大结果。

我想出了这个:

prob99 = maximum $ map ((fst)^(snd)) numbers

数字的格式如下:

numbers = [[519432,525806],[632382,518061],[78864,613712]..

为什么这不起作用?我需要更改数字的格式吗? 这里是否有一个简单的优化,我没有想到,就像一个更有效的求幂方法?

3 个答案:

答案 0 :(得分:12)

  

给一个人一条鱼,你会喂他一天,教一个人钓鱼,你会养他一辈子。

Jonno,您应该学习如何让GHC的错误消息对您有所帮助,以及“undefined drop in”方法(现在让我们关注它)。

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!

答案 1 :(得分:5)

什么不起作用是你的程序的类型一致性。您正尝试将函数(^)(简化类型Int -> Int -> Int)应用于类型(a,a) -> a(不是Int)的参数。

最简单的方法可能是直接生成对列表而不是列表列表。然后,您可以(几乎)直接将(^)函数应用于它们,首先取消它。

numbers = [(519432,525806),(632382,518061),(78864,613712)...
prob99 = maximum $ map (uncurry (^)) numbers

如果您坚持使用子列表,可以直接对它们进行模式匹配,从而改善Matajon的解决方案:

prob99 = maximum $ map (\[x,y] -> x^y) numbers

或者,如果您一直处于无点样式,您可以充分利用Control.Arrow中的运算符。 (就这种情况而言,在详细程度上没有多大帮助)

prob99 = maximum $ map ((!!0) &&& (!!1) >>> uncurry (^)) numbers

答案 2 :(得分:4)

因为fst和snd是在对上定义的(类型为fst ::(a,b) - &gt; a和snd ::(a,b) - &gt; b)。第二个问题是(fst)^(snd),你无法对函数进行幂函数。

prob99 = maximum $ map (\xs -> (head xs)^(head (tail xs))) numbers

prob99 = maximum $ map (\xs -> (xs !! 0)^(xs !! 1)) numbers