Sorting Haskell:多属性排序不够通用
我正在尝试实现一个可对任何内容列表进行排序的多属性排序Sorting Haskell:多属性排序不够通用,sorting,haskell,generics,Sorting,Haskell,Generics,我正在尝试实现一个可对任何内容列表进行排序的多属性排序 import Data.Ord (Ordering, Down (..), comparing) import Data.List (sortBy) import Data.Monoid (mconcat) data Order a = ASC a | DESC a orderBy :: Ord b => [Order (a -> b)] -> [a] -> [a] orderBy rankedPropertie
import Data.Ord (Ordering, Down (..), comparing)
import Data.List (sortBy)
import Data.Monoid (mconcat)
data Order a = ASC a | DESC a
orderBy :: Ord b => [Order (a -> b)] -> [a] -> [a]
orderBy rankedProperties unsorted =
sortBy rankedCompare unsorted
where
rankedCompare x y =
mconcat $ map
(\property ->
case property of
ASC f -> comparing f x y
DESC f -> comparing (Down . f) x y
) rankedProperties
它现在适用于元组和记录,但我发现了一个问题。问题是orderBy
中的b
必须相同。这是考虑到:
data Row = Row { shortListed :: Bool, cost :: Float, distance1 :: Int, distance2 :: Int } deriving (Show, Eq)
我想说:orderBy[ASC短名单,DESC cost]listofrows
但返回的错误是:
<interactive>:1:31:
Couldn't match type ‘Float’ with ‘Bool’
Expected type: Row -> Bool
Actual type: Row -> Float
In the first argument of ‘ASC’, namely ‘cost’
In the expression: ASC cost
:1:31:
无法将类型“Float”与“Bool”匹配
预期类型:行->布尔
实际类型:行->浮动
在“ASC”的第一个参数中,即“成本”
在表达式中:ASC成本
我需要一种方法使b
类型成为泛型,因为b
只需要被比较
函数比较::Ord a=>(b->a)->b->b->Ordering才能接受
我已经读了一些关于存在类型和异构列表的内容,但我不确定如何继续。由于我们有幺半群排序和实例幺半群b=>幺半群(a->b)
在前奏曲中,我们也有幺半群(a->a->排序)
,通过迭代函数实例两次。这让我们能够非常简单地解决问题,而不存在任何问题:
import Data.Ord (Ordering, comparing)
import Data.List (sortBy)
import Data.Monoid ((<>), mconcat)
data Row = Row {
shortListed :: Bool,
cost :: Float,
distance1 :: Int,
distance2 :: Int
} deriving (Show, Eq)
asc, desc :: Ord b => (a -> b) -> a -> a -> Ordering
asc = comparing
desc = flip . asc
list :: [Row]
list = [Row False 0 10 20, Row True 10 30 40]
list' :: [Row]
list' = sortBy (asc shortListed <> desc cost <> asc distance1) list
由于在Prelude
中有Monoid排序
和实例Monoid b=>Monoid(a->b)
,因此通过迭代函数实例两次,我们也有Monoid(a->a->Ordering)
。这让我们能够非常简单地解决问题,而不存在任何问题:
import Data.Ord (Ordering, comparing)
import Data.List (sortBy)
import Data.Monoid ((<>), mconcat)
data Row = Row {
shortListed :: Bool,
cost :: Float,
distance1 :: Int,
distance2 :: Int
} deriving (Show, Eq)
asc, desc :: Ord b => (a -> b) -> a -> a -> Ordering
asc = comparing
desc = flip . asc
list :: [Row]
list = [Row False 0 10 20, Row True 10 30 40]
list' :: [Row]
list' = sortBy (asc shortListed <> desc cost <> asc distance1) list
我本来想接受一个函数,它会产生一个排序
,但我认为它会产生太多的噪音,重复进行比较
。然而,我没有意识到只需将比较
包装到升序和降序构造函数中。我正在考虑只接受一个生成排序
的函数,但我认为重复的比较
会产生太多噪音。然而,我没有意识到只需将比较
包装成升序和降序构造函数。