    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 = (Hash -> a -> Hash) -> Hash -> t a -> Hash
    forall b a. (b -> a -> b) -> b -> t a -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' (\Hash
    h a
    a -> Hash
    h Hash -> Hash -> Hash
    `combine` a -> Hash
    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 = Int -> Hash
    forall a. Hashable a => a -> Hash
    hash (Word -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word
    w :: Int)

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

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

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

    instance Hashable Int64 where
        hash :: Int64 -> Hash
    hash Int64
    i = Word64 -> Hash
    forall a. Hashable a => a -> Hash
    hash (Int64 -> Word64
    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 = String -> Hash
    forall a. Hashable a => a -> Hash
    hash (String -> Hash) -> (Integer -> String) -> Integer -> Hash
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Integer -> String
    forall a. Show a => a -> String
    show

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

    instance Hashable Double where
        hash :: Double -> Hash
    hash = Double -> 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 = (a -> Hash
    forall a. Hashable a => a -> Hash
    hash (a -> Hash) -> a -> Hash
    forall a b. (a -> b) -> a -> b
    $ Ratio a -> a
    forall a. Ratio a -> a
    numerator Ratio a
    r) Hash -> Hash -> Hash
    `combine` (a -> Hash
    forall a. Hashable a => a -> Hash
    hash (a -> Hash) -> a -> Hash
    forall a b. (a -> b) -> a -> b
    $ Ratio a -> a
    forall a. Ratio a -> a
    denominator Ratio a
    r)

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

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

    instance Hashable Bool where
        hash :: Bool -> Hash
    hash = Int -> Hash
    forall a. Hashable a => a -> Hash
    hash (Int -> Hash) -> (Bool -> Int) -> Bool -> Hash
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Bool -> Int
    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) = a -> Hash
    forall a. Hashable a => a -> Hash
    hash a
    a Hash -> Hash -> Hash
    `combine` b -> Hash
    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) = a -> Hash
    forall a. Hashable a => a -> Hash
    hash a
    a Hash -> Hash -> Hash
    `combine` b -> Hash
    forall a. Hashable a => a -> Hash
    hash b
    b Hash -> Hash -> Hash
    `combine` c -> Hash
    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) = a -> Hash
    forall a. Hashable a => a -> Hash
    hash a
    a Hash -> Hash -> Hash
    `combine` b -> Hash
    forall a. Hashable a => a -> Hash
    hash b
    b Hash -> Hash -> Hash
    `combine` c -> Hash
    forall a. Hashable a => a -> Hash
    hash c
    c Hash -> Hash -> Hash
    `combine` d -> Hash
    forall a. Hashable a => a -> Hash
    hash d
    d

    instance Hashable a => Hashable (Maybe a) where
        hash :: Maybe a -> Hash
    hash = Hash -> (a -> Hash) -> Maybe a -> Hash
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Hash
    hF (\a
    a -> a -> Hash
    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) = a -> Hash
    forall a. Hashable a => a -> Hash
    hash a
    a Hash -> Hash -> Hash
    `combine` Hash
    hT
        hash (Right b
    b) = b -> Hash
    forall a. Hashable a => a -> Hash
    hash b
    b Hash -> Hash -> Hash
    `combine` Hash
    hF