Вам нужно только O (n) (2 n - 1, если быть точным) определений, чтобы указать общий порядок, если вы указываете случаи в порядке возрастания приоритет:
instance Ord FooPriorityA where
compare (FooPriorityA x) (FooPriorityA y) | x == y = EQ -- Use the Eq instance
-- Bar is the smallest
| x == Bar = LT
| y == Bar = GT
-- Baz is the next smallest
| x == Baz = LT
| y == Baz = GT
-- Proceed in the desired order.
-- You don't need to say anything
-- explicit about the largest value
Первый случай (x == y
) охватывает O (n) возможностей. Каждый последующий случай может выглядеть неполным, но он несет в себе подразумеваемую информацию о том, что каждый предыдущий случай является ложным. Например, x == Bar = LT
не означает, что каждый случай, когда x == Bar
оценивается как LT
; случай, когда x == Bar && y == Bar
уже обработан, поэтому второй случай действительно неявно x == Bar && y /= Bar
.
Аналогично, случай 4 (x == Baz
) предполагает, что y /= Baz
(подразумевается несоответствием случая 1) и y /= Bar
(подразумевается несоответствием случая 3). Следовательно, любое оставшееся возможное значение для y
фактически больше Baz
.
Чем дальше вы продвигаетесь по списку, тем меньше остается необработанных дел. В конце концов, вам не нужно говорить ничего явного о самом большом предмете; вся информация о его сравнении с другими элементами n - 1 уже была получена в предыдущих случаях.
Также имейте в виду, что ваше определение f
составляет половину (fromEnum
) минимальной реализации экземпляра класса Enum
, который затем можно использовать для определения своего Ord
экземпляра.
instance Enum FooPriorityA where
fromEnum Bar = 1
fromEnum Baz = 2
fromEnum Qux = 3
toEnum 1 = Bar
toEnum 2 = Baz
toEnum 3 = Qux
instance Ord FooPriorityA where
compare x y = compare (fromEnum x) (fromEnum y)
-- compare = compare `on` Data.Function.fromEnum
person
chepner
schedule
01.08.2016