module Data.Hash.Instances ( Hashable(..), hashFoldable )

where

import Data.Hash.Base

import Data.Word
import Data.Int
import Data.Ratio
import Data.Foldable

class Hashable a where
    hash :: a -> Hash

hashFoldable :: (Foldable t, Hashable a) => t a -> Hash
hashFoldable :: forall (t :: * -> *) a. (Foldable t, Hashable a) => t a -> Hash
hashFoldable = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\Hash
h a
a -> Hash
h Hash -> Hash -> Hash
`combine` forall a. Hashable a => a -> Hash
hash a
a) Hash
h0


instance Hashable Word8 where
    hash :: Word8 -> Hash
hash = Word8 -> Hash
hashWord8

instance Hashable Word16 where
    hash :: Word16 -> Hash
hash = Word16 -> Hash
hashWord16

instance Hashable Word32 where
    hash :: Word32 -> Hash
hash = Word32 -> Hash
hashWord32

instance Hashable Word64 where
    hash :: Word64 -> Hash
hash = Word64 -> Hash
hashWord64

instance Hashable Word where
    hash :: Word -> Hash
hash Word
w = forall a. Hashable a => a -> Hash
hash (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
w :: Int)

instance Hashable Int8 where
    hash :: Int8 -> Hash
hash Int8
i = forall a. Hashable a => a -> Hash
hash (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
i :: Word8)

instance Hashable Int16 where
    hash :: Int16 -> Hash
hash Int16
i = forall a. Hashable a => a -> Hash
hash (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int16
i :: Word16)

instance Hashable Int32 where
    hash :: Int32 -> Hash
hash Int32
i = forall a. Hashable a => a -> Hash
hash (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
i :: Word32)

instance Hashable Int64 where
    hash :: Int64 -> Hash
hash Int64
i = forall a. Hashable a => a -> Hash
hash (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
i :: Word64)

instance Hashable Int where
    hash :: Int -> Hash
hash = Int -> Hash
hashInt

instance Hashable Integer where
    -- a very inefficient instance, but i don't have time to mess
    -- with internal representations now...
    hash :: Integer -> Hash
hash = forall a. Hashable a => a -> Hash
hash forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show

instance Hashable Float where
    hash :: Float -> Hash
hash = forall a. Storable a => a -> Hash
hashStorable

instance Hashable Double where
    hash :: Double -> Hash
hash = forall a. Storable a => a -> Hash
hashStorable

instance (Integral a, Hashable a) => Hashable (Ratio a) where
    hash :: Ratio a -> Hash
hash Ratio a
r = (forall a. Hashable a => a -> Hash
hash forall a b. (a -> b) -> a -> b
$ forall a. Ratio a -> a
numerator Ratio a
r) Hash -> Hash -> Hash
`combine` (forall a. Hashable a => a -> Hash
hash forall a b. (a -> b) -> a -> b
$ forall a. Ratio a -> a
denominator Ratio a
r)

instance Hashable Char where
    hash :: Char -> Hash
hash = forall a. Hashable a => a -> Hash
hash forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Enum a => a -> Int
fromEnum

instance Hashable a => Hashable [a] where
    hash :: [a] -> Hash
hash = forall (t :: * -> *) a. (Foldable t, Hashable a) => t a -> Hash
hashFoldable

instance Hashable Bool where
    hash :: Bool -> Hash
hash = forall a. Hashable a => a -> Hash
hash forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Enum a => a -> Int
fromEnum

instance Hashable () where
    hash :: () -> Hash
hash () = Hash
h0

instance (Hashable a, Hashable b) => Hashable (a,b) where
    hash :: (a, b) -> Hash
hash (a
a,b
b) = forall a. Hashable a => a -> Hash
hash a
a Hash -> Hash -> Hash
`combine` forall a. Hashable a => a -> Hash
hash b
b

instance (Hashable a, Hashable b, Hashable c) => Hashable (a,b,c) where
    hash :: (a, b, c) -> Hash
hash (a
a,b
b,c
c) = forall a. Hashable a => a -> Hash
hash a
a Hash -> Hash -> Hash
`combine` forall a. Hashable a => a -> Hash
hash b
b Hash -> Hash -> Hash
`combine` forall a. Hashable a => a -> Hash
hash c
c

instance (Hashable a, Hashable b, Hashable c, Hashable d) => Hashable (a,b,c,d)
  where
    hash :: (a, b, c, d) -> Hash
hash (a
a,b
b,c
c,d
d) = forall a. Hashable a => a -> Hash
hash a
a Hash -> Hash -> Hash
`combine` forall a. Hashable a => a -> Hash
hash b
b Hash -> Hash -> Hash
`combine` forall a. Hashable a => a -> Hash
hash c
c Hash -> Hash -> Hash
`combine` forall a. Hashable a => a -> Hash
hash d
d

instance Hashable a => Hashable (Maybe a) where
    hash :: Maybe a -> Hash
hash = forall b a. b -> (a -> b) -> Maybe a -> b
maybe Hash
hF (\a
a -> forall a. Hashable a => a -> Hash
hash a
a Hash -> Hash -> Hash
`combine` Hash
hT)

instance (Hashable a, Hashable b) => Hashable (Either a b) where
    hash :: Either a b -> Hash
hash (Left  a
a) = forall a. Hashable a => a -> Hash
hash a
a Hash -> Hash -> Hash
`combine` Hash
hT
    hash (Right b
b) = forall a. Hashable a => a -> Hash
hash b
b Hash -> Hash -> Hash
`combine` Hash
hF