Skip to content

Instantly share code, notes, and snippets.

@googleson78
Last active January 13, 2020 05:16
Show Gist options
  • Save googleson78/c368cc132bf872181d1e460026d9962b to your computer and use it in GitHub Desktop.
Save googleson78/c368cc132bf872181d1e460026d9962b to your computer and use it in GitHub Desktop.
uh..
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE DerivingStrategies #-}
module HashAbuse where
import Data.Hashable
import Data.Function (on)
newtype Vertical = Vertical {getVertical :: (Int, Int)}
deriving stock Show
deriving Eq via EqOnHash Vertical
instance Hashable Vertical where
hashWithSalt _ = error "shouldn't be called"
hash (Vertical (_, y)) = y
newtype RevDiag = RevDiag {getRevDiag :: (Int, Int)}
deriving stock Show
deriving Eq via EqOnHash RevDiag
instance Hashable RevDiag where
hashWithSalt _ = error "shouldn't be called"
hash (RevDiag (x, y)) = x + y
newtype MainDiag = MainDiag {getMainDiag :: (Int, Int)}
deriving stock Show
deriving Eq via EqOnHash MainDiag
instance Hashable MainDiag where
hashWithSalt _ = error "shouldn't be called"
hash (MainDiag (x, y)) = x - y
newtype EqOnHash a = EqOnHash {getEqOnHash :: a}
instance Hashable a => Eq (EqOnHash a) where
(==) = (==) `on` (hash . getEqOnHash)
@Icelandjack
Copy link

Once we get dependent types we could parameterise EqOnHash on the function and just naming it

type On :: forall a b. (a -> b) -> Type

newtype On f where
 On :: a -> On @a @b f

If I got that right we will be able to write

instance pi f. Eq (On f) where
 (==) :: On f -> On f -> Bool
 On a == On b = f a == f b

instance pi f. Ord (On f) where
 compare :: On f -> On f -> Ordering
 compare (On a) (On b) = compare (f a) (f b)

@googleson78
Copy link
Author

googleson78 commented Jan 13, 2020

@Icelandjack
Yes! Nearly every time I use DerivingVia I want this same thing myself.

(btw, do you have an automatic magic detector for DerivingVia usage? 😅)

(also huge thanks for the extension!)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment