有maximumWith之类的东西吗? [英] Is there such a thing as maximumWith?
问题描述
具体地说,我正在搜索函数'maximumWith',
Specifically I'm searching for a function 'maximumWith',
maximumWith :: (Foldable f, Ord b) => (a -> b) -> f a -> a
以下行为:
maximumWith length [[1, 2], [0, 1, 3]] == [0, 1, 3]
maximumWith null [[(+), (*)], []] == []
maximumWith (const True) x == head x
我的用例是选择列表中最长的单词.
为此,我想要类似于 maximumWith length
的东西.
My use case is picking the longest word in a list.
For this I'd like something akin to maximumWith length
.
我以为存在这样的事情,因为 sortWith
等存在.
I'd thought such a thing existed, since sortWith
etc. exist.
推荐答案
让我一起收集注释中的所有注释...
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
usesOrd
overloading.sortWith = sortBy . comparing
is the analogue of your desiredmaximumWith
. 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
), andnewtype
constructors. YMMV on simple arithmetic and data constructors. Between this inefficiency, the simplicity of the definition, and its location inGHC.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 #-}
这篇关于有maximumWith之类的东西吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!