2016-05-21 7 views
1

私は、何かのリストで動作するランク付きのマルチプロパティソートを実装しようとしていました。Haskell:複数プロパティソートが十分に汎用的ではありません

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 

これはタプルとレコード用に機能しますが、問題が見つかりました。問題はorderBybが同じでなければならないということです。 orderBy [ASC shortListed, DESC cost] listofrows:私が言うことができるようにしたい

data Row = Row { shortListed :: Bool, cost :: Float, distance1 :: Int, distance2 :: Int } deriving (Show, Eq) 

:それはこのことを考慮しています。

れるが戻ってくるエラー:

<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 

bはだけは本当にcomparing機能comparing :: Ord a => (b -> a) -> b -> b -> Orderingで許容しなければならないので、私は、bタイプが一般的なようにする方法が必要です。

私は実在のタイプと異種のリストについて少しは読んだことがありますが、どのように進むべきかわかりません。

答えて

5

Monoid Orderinginstance Monoid b => Monoid (a -> b)Preludeにあるため、関数インスタンスを2回反復することで、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 

:これは、私たちはexistentialsせずに、非常に単純な問題を解決することができます

orderBy :: [a -> a -> Ordering] -> [a] -> [a] 
orderBy = sortBy . mconcat 

list'' :: [Row] 
list'' = orderBy [asc shortListed, desc cost, asc distance1] list 
+0

私はちょうど 'Ordering'を作り出す機能を受け入れることを考えていたが、私はそれがあまりにも多くを作成するだろうと思いました反復的な「比較」を伴うノイズ。しかし、私は昇順と降順のコンストラクタに 'comparison'をラップするだけではわかりませんでした。 – CMCDragonkai

関連する問題