查找元组列表中的最大元素

时间:2013-08-08 05:08:34

标签: haskell

我是Haskell的初学者。我有一个我在Haskell中使用的元组列表:结构就像这样[(a,b),(c,d),(e,f),(g,h)]

我想要的是根据第二个值返回此元组中的最大元素: 因此,如果元组列表为[(4,8),(9,10),(15,16),(10,4)],我希望最大元素为(15,16)

但我不知道该怎么做。这是我到目前为止的尝试,

maximum' ::  (Ord a) => (Num a) => [(a,b)] -> a  
maximum' [] = error "maximum of empty list"  
maximum' [(x,y)] = -1
maximum' (x:xs)   
  | snd x > snd(xs !! maxTail) = 0
  | otherwise = maxTail  
  where maxTail = maximum' xs + 1

我收到此错误消息对我来说没有意义:

newjo.hs:23:25:
Could not deduce (a ~ Int)
from the context (Ord a, Num a)
  bound by the type signature for
             maximum' :: (Ord a, Num a) => [(a, b)] -> a
  at newjo.hs:19:14-47
  `a' is a rigid type variable bound by
      the type signature for maximum' :: (Ord a, Num a) => [(a, b)] -> a
      at newjo.hs:19:14
In the second argument of `(!!)', namely `maxTail'
In the first argument of `snd', namely `(xs !! maxTail)'
In the second argument of `(>)', namely `snd (xs !! maxTail)'`

我需要一些帮助来解决这个问题。

4 个答案:

答案 0 :(得分:23)

惯用的方法是使用maximumBy (comparing snd)

a ~ Int消息表示由于某种原因,Haskell推断a必须是Int,但类型签名不会将其限制为IntAs Amos notes in the comments和GHC告诉您其来源位置,这是因为您将其用作!!的第二个参数,即Int

答案 1 :(得分:9)

使用库的惯用方法是使用maximumBy

maximumBy :: (a -> a -> Ordering) -> [a] -> a

然后剩下的就是定义a -> a -> Ordering类型的函数,因此它知道如何对元素进行排序。构造Ordering对象的常用方法是使用

compare :: (Ord a) => a -> a -> Ordering

答案 2 :(得分:4)

到目前为止提供的解决方案非常优雅,您应该在您编写的任何实际代码中使用它们。但这是一个使用与您正在使用的相同模式匹配样式的版本。

maximum' :: Ord a => [(t, a)] -> (t, a)
maximum' []     = error "maximum of empty list"
maximum' (x:xs) = maxTail x xs
  where maxTail currentMax [] = currentMax
        maxTail (m, n) (p:ps)
          | n < (snd p) = maxTail p ps
          | otherwise   = maxTail (m, n) ps

此解决方案避免了周围的杂耍索引,而只是跟踪当前最大元素,该元素在遍历整个列表时返回。避免使用列表的索引通常被视为良好做法。

答案 3 :(得分:1)

值得注意的是,Haskell中的元组是Ord的实例。因此可以对它们进行排序和比较。它们使用字典顺序排序(主要由元组的第一个元素,次要的第二个元素等),所以跟随:

maximum [(1,1),(1,8),(2,1),(2,6)] == (2,6)

如果你想得到最大二元素的元组。你可以只交换 maximum 函数的元组元素,然后像这样交换结果元素:

maximum' :: (Ord a, Ord b) => [(a,b)] -> (a,b)
maximum' l = swap $ maximum $ map swap l
             where swap (x, y) = (y, x) 

虽然为了使其工作,但两个元组元素必须是Ord的实例。