更新时间: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 #-}