首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >haskell按值排序类型及其字段

haskell按值排序类型及其字段
EN

Stack Overflow用户
提问于 2022-11-02 09:50:12
回答 1查看 63关注 0票数 1

我有这样的类型

代码语言:javascript
复制
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

将列表fdate字段排序时。

代码语言:javascript
复制
instance Ord Fruit where
    compare f1 f2 =  compare (getDate f1) (getDate f2)

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

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

代码语言:javascript
复制
[Apple  2020-01-01, Balance  2020-01-01, Apple 2020-02-01  ,Balana 2020-02-01]

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-02 11:26:31

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

最直截了当的不是你想要的,而是你想知道的。

代码语言:javascript
复制
data Fruit = Apple Date
           | Balana Date 
           | Orange Date
           deriving (Eq, Ord)

这为您的输入创建了自动顺序,但在本例中,它将首先比较水果和Date .你想要的正好相反。

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

代码语言:javascript
复制
-- 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)

不同的造型

现在,你可能是在用一种非惯用的方式来模拟你的类型。如果所有项目都有日期,则应将类型编码为成对,如下所示

代码语言:javascript
复制
-- 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

例如,此程序按预期使用建议的类型对列表进行排序。

代码语言:javascript
复制
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
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74287224

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档