Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

haskell check equality by function

In haskell I can use

sortBy (comparing snd) 

to sort by the second value in a tuple.

Is there an equivalent function for testing equivalency? I've come up with this but maybe there is something in the standard library.

equalsBy :: Eq b => (a -> b) -> a -> a -> Bool
equalsBy f x y = f x == f y

The end goal is to group a list of pairs by their second values. With this I can do

groupBy (equalsBy snd) pairs

instead of

groupBy (\x y -> (snd x) == (snd y)) pairs
like image 480
Erik Bergsten Avatar asked Jan 17 '14 00:01

Erik Bergsten


People also ask

Can you compare functions for equality in Haskell?

Most notably, in Haskell, functions are not in the Eq typeclass (in general). Not any two functions can be compared for equality in Haskell.

How do you check for equality in Haskell?

Haskell provides a number of tests including: < (less than), > (greater than), <= (less than or equal to) and >= (greater than or equal to). These tests work comparably to == (equal to).

What does == mean in Haskell?

The == is an operator for comparing if two things are equal. It is quite normal haskell function with type "Eq a => a -> a -> Bool". The type tells that it works on every type of a value that implements Eq typeclass, so it is kind of overloaded.

Is Ord a subclass of Eq?

Ord is a subclass of Eq that is used for data types that have a total ordering (every value can be compared with another).


1 Answers

You are looking for a slightly higher level function called on:

> import Data.Function
> :t on
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c

Well how do I use that? Like this!

> :t ( (==) `on` snd )
( (==) `on` snd ) :: Eq b => (a, b) -> (a, b) -> Bool

So that means we want:

> groupBy ( (==) `on` snd) [ (1,3), (23,9), (42,9), (1,3), (48, 3), (18,18)]
[[(1,3)],[(23,9),(42,9)],[(1,3),(48,3)],[(18,18)]]

Yay!

EDIT:

I'd like to note how comparing relates to on. It is just a specialized use of on!

> :t comparing
comparing      :: Ord a => (b -> a) -> b -> b -> Ordering
> :t (compare `on`)
(compare `on`) :: Ord b => (a -> b) -> a -> a -> Ordering

(notice the type variables are swapped, but you can see the types are identical)

like image 62
Thomas M. DuBuisson Avatar answered Sep 30 '22 05:09

Thomas M. DuBuisson