且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

有maximumWith之类的东西吗?

更新时间:2023-11-28 23:21:28

让我一起收集注释中的所有注释...

Let me collect all the notes in the comments together...

让我们看一下 sort .该系列有4个功能:

Let's look at sort. There are 4 functions in the family:

  • sortBy 是实际的实现.
  • sort = sortBy比较使用 Ord 重载.
  • sortWith = sortBy.比较是您所需的 maximumWith 的类似物.但是,此功能有问题.元素的排名是通过将给定的映射函数应用于元素来进行的.但是,排名不会被记录下来,因此,如果一个元素需要多次比较,排名将被重新计算.如果排名功能非常便宜,则只能无罪地使用.此类功能包括选择器(例如 fst )和 newtype 构造函数.YMMV在简单的算术和数据构造函数上.在这种低效率,定义的简单性及其在 GHC.Exts 中的位置之间,很容易推断出它的使用频率不高.
  • sortOn 通过在排名功能下将每个元素用其图像装饰成对,按等级排序,然后删除它们,从而解决了效率低下的问题.
  • sortBy is the actual implementation.
  • sort = sortBy compare uses Ord overloading.
  • sortWith = sortBy . comparing is the analogue of your desired maximumWith. However, this function has an issue. The ranking of an element is given by applying the given mapping function to it. However, the ranking is not memoized, so if an element needs to compared multiple times, the ranking will be recomputed. You can only use it guilt-free if the ranking function is very cheap. Such functions include selectors (e.g. fst), and newtype constructors. YMMV on simple arithmetic and data constructors. Between this inefficiency, the simplicity of the definition, and its location in GHC.Exts, it's easy to deduce that it's not used that often.
  • sortOn fixes the inefficiency by decorating each element with its image under the ranking function in a pair, sorting by the ranks, and then erasing them.

前两个在 maximum 中具有类似物: maximumBy maximum . sortWith 没有类比;您***每次都写出 maximumBy(比较_).即使这样会更有效,也没有 maximumOn .定义 maximumOn 的最简单方法可能就是复制 sortOn :

The first two have analogues in maximum: maximumBy and maximum. sortWith has no analogy; you may as well write out maximumBy (comparing _) every time. There is also no maximumOn, even though such a thing would be more efficient. The easiest way to define a maximumOn is probably just to copy sortOn:

maximumOn :: (Functor f, Foldable f, Ord r) => (a -> r) -> f a -> a
maximumOn rank = snd . maximumBy (comparing fst) . fmap annotate
  where annotate e = let r = rank e in r `seq` (r, e)

maximumBy 中有一些有趣的代码,无法在列表上进行适当的优化.它也可以使用

There's a bit of interesting code in maximumBy that keeps this from optimizing properly on lists. It also works to use

maximumOn :: (Foldable f, Ord r) => (a -> r) -> f a -> a
maximumOn rank = snd . fromJust . foldl' max' Nothing
    where max' Nothing x = let r = rank x in r `seq` Just (r, x)
          max' old@(Just (ro, xo)) xn = let rn = rank xn
                                         in case ro `compare` rn of
                                                 LT -> Just (rn, xo)
                                                 _ -> old

这些实用指示可能有用:

These pragmas may be useful:

{-# SPECIALIZE maximumOn :: Ord r => (a -> r) -> [a] -> a #-}
{-# SPECIALIZE maximumOn :: (a -> Int) -> [a] -> a #-}