DSL for creating compare functions
This small module provides a concise DSL for creating comparison functions.
Oftentimes, you will be able to convert a value to another, comparable, value. by
takes a function which converts a value to a comparable value. For example, to get a list of bank account holders, ordered by wealth:
>>> List.sortWith (Compare.by (.transactions >> List.sum) descending)
... [ { holder = "James Joyce", transactions = [100.00, -25.00, -2.99, 30.00] }
... , { holder = "Bill Bryson", transactions = [999.02, -233.00, -400.00, -300.00] }
... ]
... |> List.map .holder
[ "James Joyce", "Bill Bryson" ]
by : (a -> comparable) -> ((a -> a -> Basics.Order) -> b) -> b
thenBy
and thenByReverse
. A typical example would be sorting an address book by last name then first name:>>> List.sortWith (Compare.by .lastName thenBy .firstName thenByReverse .age ascending)
... [ { firstName = "Andy", lastName = "Baldwin", age = 90 }
... , { firstName = "Bert", lastName = "Anderson", age = 23 }
... , { firstName = "Alec", lastName = "Anderson", age = 8 }
... , { firstName = "Alec", lastName = "Anderson", age = 100 }
... ]
[ { firstName = "Alec", lastName = "Anderson", age = 100 }
, { firstName = "Alec", lastName = "Anderson", age = 8 }
, { firstName = "Bert", lastName = "Anderson", age = 23 }
, { firstName = "Andy", lastName = "Baldwin", age = 90 }
]
thenBy : (a -> a -> Basics.Order) -> (a -> comparable) -> ((a -> a -> Basics.Order) -> b) -> b
ascending : (a -> a -> Basics.Order) -> a -> a -> Basics.Order
descending : (a -> a -> Basics.Order) -> a -> a -> Basics.Order
If converting values to comparable types alone is not enough, arbitrary comparison functions can be introducted by swapping out by
for with
.
>>> Compare.with
... (\player opponent ->
... if List.member (opponent.name) player.alwaysBeats then
... GT
... else if List.member (player.name) opponent.alwaysBeats then
... LT
... else
... EQ
... )
... thenBy .strength ascending
... { name = "Ogre"
... , strength = 100
... , alwaysBeats = [ "Yeti", "Dragon" ]
... }
... { name = "Cyborg"
... , strength = 20
... , alwaysBeats = [ "Ogre", "Kappa" ]
... }
LT
with : (a -> a -> Basics.Order) -> ((a -> a -> Basics.Order) -> b) -> b
thenWith : (a -> a -> Basics.Order) -> (a -> a -> Basics.Order) -> ((a -> a -> Basics.Order) -> b) -> b
thenWithReverse : (a -> a -> Basics.Order) -> (a -> a -> Basics.Order) -> ((a -> a -> Basics.Order) -> b) -> b