让我把评论里的所有笔记都收集起来……
让我们看看sort
。家庭有4个功能:
sortBy
是实际的实现。
sort = sortBy compare
使用Ord
重载。
sortWith = sortBy . comparing
是您想要的类似物maximumWith
。但是,这个函数有一个问题。元素的排名是通过将给定的映射函数应用于它来给出的。但是,排名不会被记忆,所以如果一个元素需要多次比较,排名将被重新计算。如果排名功能非常便宜,您只能无罪地使用它。这样的函数包括选择器(例如fst
)和newtype
构造器。YMMV 关于简单算术和数据构造函数。在这种低效率、定义的简单性以及它在 中的位置之间GHC.Exts
,很容易推断它不经常使用。
sortOn
通过在一对排序函数下用其图像装饰每个元素,按等级排序,然后删除它们来解决效率低下的问题。
前两个在maximum
:maximumBy
和maximum
. sortWith
没有类比;你不妨maximumBy (comparing _)
每次都写出来。也没有maximumOn
,即使这样的事情会更有效率。定义 a 的最简单方法maximumOn
可能只是复制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
可以防止它在列表上正确优化。它也可以使用
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
这些 pragma 可能有用:
{-# SPECIALIZE maximumOn :: Ord r => (a -> r) -> [a] -> a #-}
{-# SPECIALIZE maximumOn :: (a -> Int) -> [a] -> a #-}