haskell按值及其字段对类型进行排序



我有类似的类型

data Fruit = Apple Date
| Balana Date 
| Orange Date
f = [Apple 2020-01-01 ,Apple 2020-02-01 
,Balana 2020-01-01 ,Balana 2020-02-01]
getDate:: Fruit -> Date
getDate (Apple x) = x
getDate (Balana x) = x
getDate (Orange x) = x

当按CCD_ 2字段对列表CCD_。

instance Ord Fruit where
compare f1 f2 =  compare (getDate f1) (getDate f2)

但是,问题是,如何设置规则来订购Apple 2020-01-01Balance 2020-01-01

如果我想先对日期进行排序,如果不同类型的水果的date相同,我会先订购Apple,然后订购Balance,再订购Orange

[Apple  2020-01-01, Balance  2020-01-01, Apple 2020-02-01  ,Balana 2020-02-01]

谢谢!

您可以使用一些不同的方法:

最直接的不是你想要什么,而是用来了解

data Fruit = Apple Date
| Balana Date 
| Orange Date
deriving (Eq, Ord)

这会为您键入创建自动订单,但在这种情况下,它会先比较水果,然后比较Date。。。这正是你想要的相反。

因此,我们需要手动定义一个f0实例。


-- This get the date from fruit
getDate :: Fruit -> Date
getDate (Apple x) = x
getDate (Balana x) = x
getDate (Orange x) = x
-- This function compares the fruit with no date.
fruitOrder :: Fruit -> Fruit -> Ordering
fruitOrder (Apple _)  (Apple _)  = EQ
fruitOrder (Apple _)  _          = LT
fruitOrder (Orange _) (Orange _) = EQ
fruitOrder (Orange _) _          = GT
fruitOrder (Balana _)  (Balana _) = EQ
fruitOrder (Balana _)  (Apple _)  = GT
fruitOrder (Balana _)  (Orange _) = LT
-- Your ordering is a combination of both
instance Ord Fruit where
compare f g = comparing getDate f g <> fruitOrder f g
--            |                     |- This returns the first not EQ value or EQ if both are equal
--            |- comparing func x y == compare (func y) (func y)

不同的建模

现在,您可能正在以一种非惯用的方式对类型进行建模。如果你的所有物品都有一个日期,那么你应该将你的类型编码为成对的,如下所示

-- This is an alternative representation. You have Fruit types ordered as written
data FruitType = Apple | Banana | Orange deriving (Eq, Ord)
-- A fruit is a Date and a FruitType, this is Record syntax
-- you can think of it as C's structs or Python's dataclasses.
data Fruit = Fruit {getDate :: Date, getType :: FruitType} deriving (Eq, Ord)
-- The derived order is lexicographic, meaning they are ordered by the first field, and then by the second field

例如,该程序使用建议的类型按预期订购您的列表

import Data.List
type Date = String -- For the sake of example
-- This is an alternative representation. You have Fruit types ordered as written
data FruitType = Apple | Banana | Orange deriving (Show, Eq, Ord)
-- A fruit is a Date and a FruitType, this is Record syntax
-- you can think of it as C's structs of Python's dataclasses.
data Fruit = Fruit {getDate :: Date, getType :: FruitType} deriving (Show, Eq, Ord)
f = [ Fruit "2020-01-01" Apple
, Fruit "2020-02-01" Apple
, Fruit "2020-01-01" Banana
, Fruit "2020-02-01" Banana]

main = print $ sort f

最新更新