Data.Hashable.Lifted

hashable-1.2.5.0: A class for types that can be converted to a hash value

Copyright | (c) Milan Straka 2010 (c) Johan Tibell 2011 (c) Bryan O'Sullivan 2011, 2012
License | BSD-style
Maintainer | johan.tibell@gmail.com
Stability | provisional
Portability | portable
Safe Haskell | None
Language | Haskell98

Data.Hashable.Lifted

Contents

- Type Classes
- Auxiliary Functions
- Motivation

Description

Lifting of the `Hashable` class to unary and binary type constructors. These classes are needed to express the constraints on arguments of types that are parameterized by type constructors. Fixed-point data types and monad transformers are such types.

Synopsis

- class Hashable1 t where
- class Hashable2 t where
- hashWithSalt1 :: (Hashable1 f, Hashable a) => Int -> f a -> Int
- hashWithSalt2 :: (Hashable2 f, Hashable a, Hashable b) => Int -> f a b -> Int
- defaultLiftHashWithSalt :: (Hashable2 f, Hashable a) => (Int -> b -> Int) -> Int -> f a b -> Int

# Type Classes

class Hashable1 t where #

Methods

liftHashWithSalt :: (Int -> a -> Int) -> Int -> t a -> Int #

Lift a hashing function through the type constructor.

liftHashWithSalt :: (Generic1 t, GHashable One (Rep1 t)) => (Int -> a -> Int) -> Int -> t a -> Int #

Lift a hashing function through the type constructor.

Instances

Hashable1 [] # |
Methods liftHashWithSalt :: (Int -> a -> Int) -> Int -> [a] -> Int #
Hashable1 Maybe # |
Methods liftHashWithSalt :: (Int -> a -> Int) -> Int -> Maybe a -> Int #
Hashable1 Identity # |
Methods liftHashWithSalt :: (Int -> a -> Int) -> Int -> Identity a -> Int #
Hashable1 Fixed # |
Methods liftHashWithSalt :: (Int -> a -> Int) -> Int -> Fixed a -> Int #
Hashable1 Hashed # |
Methods liftHashWithSalt :: (Int -> a -> Int) -> Int -> Hashed a -> Int #
Hashable a => Hashable1 (Either a) # |
Methods liftHashWithSalt :: (Int -> a -> Int) -> Int -> Either a a -> Int #
Hashable a1 => Hashable1 ((,) a1) # |
Methods liftHashWithSalt :: (Int -> a -> Int) -> Int -> (a1, a) -> Int #
Hashable1 (Proxy *) # |
Methods liftHashWithSalt :: (Int -> a -> Int) -> Int -> Proxy * a -> Int #
(Hashable a1, Hashable a2) => Hashable1 ((,,) a1 a2) # |
Methods liftHashWithSalt :: (Int -> a -> Int) -> Int -> (a1, a2, a) -> Int #
Hashable a => Hashable1 (Const * a) # |
Methods liftHashWithSalt :: (Int -> a -> Int) -> Int -> Const * a a -> Int #
(Hashable a1, Hashable a2, Hashable a3) => Hashable1 ((,,,) a1 a2 a3) # |
Methods liftHashWithSalt :: (Int -> a -> Int) -> Int -> (a1, a2, a3, a) -> Int #
(Hashable1 f, Hashable1 g) => Hashable1 (Sum * f g) # |
Methods liftHashWithSalt :: (Int -> a -> Int) -> Int -> Sum * f g a -> Int #
(Hashable1 f, Hashable1 g) => Hashable1 (Product * f g) # |
Methods liftHashWithSalt :: (Int -> a -> Int) -> Int -> Product * f g a -> Int #
(Hashable a1, Hashable a2, Hashable a3, Hashable a4) => Hashable1 ((,,,,) a1 a2 a3 a4) # |
Methods liftHashWithSalt :: (Int -> a -> Int) -> Int -> (a1, a2, a3, a4, a) -> Int #
(Hashable1 f, Hashable1 g) => Hashable1 (Compose * * f g) # |
Methods liftHashWithSalt :: (Int -> a -> Int) -> Int -> Compose * * f g a -> Int #
(Hashable a1, Hashable a2, Hashable a3, Hashable a4, Hashable a5) => Hashable1 ((,,,,,) a1 a2 a3 a4 a5) # |
Methods liftHashWithSalt :: (Int -> a -> Int) -> Int -> (a1, a2, a3, a4, a5, a) -> Int #
(Hashable a1, Hashable a2, Hashable a3, Hashable a4, Hashable a5, Hashable a6) => Hashable1 ((,,,,,,) a1 a2 a3 a4 a5 a6) # |
Methods liftHashWithSalt :: (Int -> a -> Int) -> Int -> (a1, a2, a3, a4, a5, a6, a) -> Int #

class Hashable2 t where #

Minimal complete definition

liftHashWithSalt2

Methods

liftHashWithSalt2 :: (Int -> a -> Int) -> (Int -> b -> Int) -> Int -> t a b -> Int #

Lift a hashing function through the binary type constructor.

Instances

Hashable2 Either # |
Methods liftHashWithSalt2 :: (Int -> a -> Int) -> (Int -> b -> Int) -> Int -> Either a b -> Int #
Hashable2 (,) # |
Methods liftHashWithSalt2 :: (Int -> a -> Int) -> (Int -> b -> Int) -> Int -> (a, b) -> Int #
Hashable a1 => Hashable2 ((,,) a1) # |
Methods liftHashWithSalt2 :: (Int -> a -> Int) -> (Int -> b -> Int) -> Int -> (a1, a, b) -> Int #
Hashable2 (Const *) # |
Methods liftHashWithSalt2 :: (Int -> a -> Int) -> (Int -> b -> Int) -> Int -> Const * a b -> Int #
(Hashable a1, Hashable a2) => Hashable2 ((,,,) a1 a2) # |
Methods liftHashWithSalt2 :: (Int -> a -> Int) -> (Int -> b -> Int) -> Int -> (a1, a2, a, b) -> Int #
(Hashable a1, Hashable a2, Hashable a3) => Hashable2 ((,,,,) a1 a2 a3) # |
Methods liftHashWithSalt2 :: (Int -> a -> Int) -> (Int -> b -> Int) -> Int -> (a1, a2, a3, a, b) -> Int #
(Hashable a1, Hashable a2, Hashable a3, Hashable a4) => Hashable2 ((,,,,,) a1 a2 a3 a4) # |
Methods liftHashWithSalt2 :: (Int -> a -> Int) -> (Int -> b -> Int) -> Int -> (a1, a2, a3, a4, a, b) -> Int #
(Hashable a1, Hashable a2, Hashable a3, Hashable a4, Hashable a5) => Hashable2 ((,,,,,,) a1 a2 a3 a4 a5) # |
Methods liftHashWithSalt2 :: (Int -> a -> Int) -> (Int -> b -> Int) -> Int -> (a1, a2, a3, a4, a5, a, b) -> Int #

# Auxiliary Functions

hashWithSalt1 :: (Hashable1 f, Hashable a) => Int -> f a -> Int #

Lift the `hashWithSalt` function through the type constructor.

    hashWithSalt1 = liftHashWithSalt hashWithSalt

hashWithSalt2 :: (Hashable2 f, Hashable a, Hashable b) => Int -> f a b -> Int #

Lift the `hashWithSalt` function through the type constructor.

    hashWithSalt2 = liftHashWithSalt2 hashWithSalt hashWithSalt

defaultLiftHashWithSalt :: (Hashable2 f, Hashable a) => (Int -> b -> Int) -> Int -> f a b -> Int #

Lift the `hashWithSalt` function halfway through the type constructor. This function makes a suitable default implementation of `liftHashWithSalt`, given that the type constructor `t` in question can unify with `f a`.

# Motivation

This type classes provided in this module are used to express constraints on type constructors in a Haskell98-compatible fashion. As an example, consider the following two types (Note that these instances are not actually provided because `hashable` does not have `transformers` or `free` as a dependency):

    newtype WriterT w m a = WriterT { runWriterT :: m (a, w) }
    data Free f a = Pure a | Free (f (Free f a))

The `Hashable1` instances for `WriterT` and `Free` could be written as:

    instance (Hashable w, Hashable1 m) => Hashable1 (WriterT w m) where
        liftHashWithSalt h s (WriterT m) =
            liftHashWithSalt (liftHashWithSalt2 h hashWithSalt) s m
    instance Hashable1 f => Hashable1 (Free f) where
        liftHashWithSalt h = go where
            go s x = case x of
                Pure a -> h s a
                Free p -> liftHashWithSalt go s p

The `Hashable` instances for these types can be trivially recovered with `hashWithSalt1`:

    instance (Hashable w, Hashable1 m, Hashable a) => Hashable (WriterT w m a) where
        hashWithSalt = hashWithSalt1
    instance (Hashable1 f, Hashable a) => Hashable (Free f a) where
        hashWithSalt = hashWithSalt1