composing two comparison functions?

落爺英雄遲暮 提交于 2020-05-09 18:39:12

问题


I'd like to sort by one property and then by another (if the first property is the same.)

What's the idiomatic way in Haskell of composing two comparison functions, i.e. a function used with sortBy?

Given

f :: Ord a => a -> a -> Ordering
g :: Ord a => a -> a -> Ordering

composing f and g would yield:

h x y = case v of
          EQ -> g x y
          otherwise -> v
        where v = f x y

回答1:


vitus points out the very cool instance of Monoid for Ordering. If you combine it with the instance instance Monoid b => Monoid (a -> b) it turns out your composition function is just (get ready):

mappend

Check it out:

Prelude Data.Monoid> let f a b = EQ
Prelude Data.Monoid> let g a b = LT
Prelude Data.Monoid> :t f `mappend` g
f `mappend` g :: t -> t1 -> Ordering
Prelude Data.Monoid> (f `mappend` g) undefined undefined 
LT
Prelude Data.Monoid> let f a b = GT
Prelude Data.Monoid> (f `mappend` g) undefined undefined 
GT

+1 for powerful and simple abstractions




回答2:


You can use the <> operator. In this example bigSort sorts string by their numerical value, first comparing length and then comparing lexicographically.

import Data.List (sortBy)
import Data.Ord (compare, comparing)

bigSort :: [String] -> [String]
bigSort = sortBy $ (comparing length) <> compare

Example:

bigSort ["31415926535897932384626433832795","1","3","10","3","5"] = 
        ["1","3","3","5","10","31415926535897932384626433832795"]

<> is an alias of mappend from the Data.Monoid module (see jberryman answer).

The (free) book Learn You a Haskell for Great Good! explains how it works here in Chapter 11

instance Monoid Ordering where  
   mempty = EQ  
   LT `mappend` _ = LT
   EQ `mappend` y = y
   GT `mappend` _ = GT

The instance is set up like this: when we mappend two Ordering values, the one on the left is kept, unless the value on the left is EQ, in which case the right one is the result. The identity is EQ.



来源:https://stackoverflow.com/questions/11486436/composing-two-comparison-functions

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!