NoRedInk / elm-compare / Compare

Tools for composing comparison functions.

A comparison function is the type of function you can pass to List.sortWith. You pass it two elements of a type and it returns an Order (defined in the Basics module and imported by default).

Comparator type


type alias Comparator a =
a -> a -> Basics.Order

A function that returns the relative ordering of two elements of a type.

Using compare functions

min : Comparator a -> a -> a -> a

Like Basics.min but using a custom comparator.

Compare.min (by String.length) "short" "longer"
--> "short"

max : Comparator a -> a -> a -> a

Like Basics.max but using a custom comparator.

Compare.max (by String.length) "short" "longer"
--> "longer"

minimum : Comparator a -> List a -> Maybe a

Like List.minimum but using a custom comparator.

minimum (by String.length) [ "longer", "short", "longest" ]
--> Just "short"

maximum : Comparator a -> List a -> Maybe a

Like List.maximum but using a custom comparator.

maximum (by String.length) [ "longer", "short", "longest" ]
--> Just "longest"

Composing compare functions

by : (a -> comparable) -> a -> a -> Basics.Order

Take a function meant for List.sortBy and turn it into a Comparator.

List.sortWith (by String.length) [ "longer", "short", "longest" ]
--> [ "short", "longer", "longest" ]

concat : List (Comparator a) -> a -> a -> Basics.Order

Compare by multiple criteria in order. The first criterium that distinguishes two elements is used.

kara : { firstName : String, lastName : String }
kara = { firstName = "Kara", lastName = "Thrace" }

william : { firstName : String, lastName : String }
william = { firstName = "William", lastName = "Adama" }

lee : { firstName : String, lastName : String }
lee = { firstName = "Lee", lastName = "Adama" }

List.sortWith (concat [ by .lastName, by .firstName ]) [ kara, william, lee  ]
--> [ lee, william, kara ]

reverse : Comparator a -> a -> a -> Basics.Order

Reverse an ordering function.

List.sortWith (by String.length |> reverse) [ "longer", "short", "longest" ]
--> [ "longest", "longer", "short" ]

compose : (a -> b) -> Comparator b -> a -> a -> Basics.Order

Apply a transformation to both incoming values before attempting to apply the previous comparator to the results

type alias Player =
    { id : Id
    , score : Score
    }

highestScoringPlayer : List Player -> Maybe Player
highestScoringPlayer players =
    players
        |> Compare.maximum (Compare.compose .score Score.compare)