amitaibu
amitaibu

Reputation: 1116

Sort list of different types

I'd like to sort a list of two different types. To do so I first create a Wrappertype, so I can mappend both types.

  1. Is having a Wrapper type the right way here?
  2. I'm not clear on how do I do the actual sorting if I'd like to sort by the delta key (i.e. fooDelta and barDelta)

The code:

import           Data.List   (sortBy)
import           Data.Monoid
import           Data.Ord    (comparing)

data Foo = Foo
    { fooLabel :: String
    , fooDelta :: Int
    } deriving (Show, Eq)

data Bar = Bar
    { barLabel   :: String
    , barDelta   :: Int
    , barAnother :: String
    } deriving (Show, Eq)

data Wrapper = WFoo Foo | WBar Bar
    deriving (Show, Eq)

sortTest :: [Wrapper]
sortTest =
    listFoo <> listBar
    where
        listFoo = [WFoo $ Foo "label1" 0, WFoo $ Foo "label2" 2]
        listBar = [WBar $ Bar "label1" 1 "another1"]

Upvotes: 1

Views: 248

Answers (1)

dkasak
dkasak

Reputation: 2703

A wrapper type is definitely a good way to do this. Since you simply want to sort your wrapped values based on a constituent Int value, you can use Data.List.sortOn.

Define a function which extracts the delta value:

delta :: Wrapper -> Int
delta (WFoo f) = fooDelta f
delta (WBar b) = barDelta b

Then use sortOn like this:

main :: IO ()
main = print $ sortOn delta sortTest

This gives the following output for your example:

[WFoo (Foo {fooLabel = "label1", fooDelta = 0}),WBar (Bar {barLabel = "label1", barDelta = 1, barAnother = "another1"}),WFoo (Foo {fooLabel = "label2", fooDelta = 2})]

Another way to do this is to define an Ord instance for your wrapper type. Then you can simply use sort on your [Wrapper] list.

Upvotes: 2

Related Questions