这段代码有效,但它很冗长,我确信有更简洁的方法。
import qualified Data.Vector as V
data Event a = Event { start :: Time
, duration :: Time
, payload :: Maybe a } deriving (Show, Eq)
instance Ord a => Ord (Event a) where
(<=) a b = start a < start b
|| start a == start b && duration a < duration b
|| start a == start b && duration a == duration b && payload a <= payload b
背后的想法是,如果一件事在另一件事之前开始,你应该把它称为较小的,甚至不要看其他两个领域。同样地,如果它们同时开始但是一个更简短,那么简短的一个就是较小的,你可以忽略第三个字段。
答案 0 :(得分:6)
使用deriving
:
data Event a = Event { start :: Time
, duration :: Time
, payload :: Maybe a } deriving (Show, Eq, Ord)
派生实例自动按字典顺序排列。
答案 1 :(得分:4)
正如@HTNW所说,自动派生的Ord
实例将起作用。在更一般的情况下,如果您需要按字典顺序对每个具有现有Ord
实例的多个项目进行排序,则可以使用自动元组Ord
实例:
instance Ord a => Ord (Event a) where
(<=) a b = order a <= order b
where order x = (start x, duration x, payload x)
答案 2 :(得分:3)
As HTNW suggests,如果可以,请使用deriving
。如果你不能(例如记录字段不是以适当的顺序,或者你实际上没有编写实例),一个非常好的选择就是compare
(或{{3} },而不是(<=)
,而不是Monoid
,然后利用Ordering
的{{1}}实例,这相当于词典顺序:
import Data.Ord (comparing)
import Data.Monoid ((<>))
instance Ord a => Ord (Event a) where
compare a b = comparing start a b
<> comparing duration a b
<> comparing payload a b
由于函数有一个Monoid
实例作用于结果,你可能会更进一步:
instance Ord a => Ord (Event a) where
compare = comparing start <> comparing duration <> comparing payload