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 |

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.

# Type Classes

class Hashable1 t where Source #

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

Lift a hashing function through the type constructor.

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

Lift a hashing function through the type constructor.

Hashable1 [] Source # | |

Hashable1 Maybe Source # | |

Hashable1 Identity Source # | |

Hashable1 Fixed Source # | |

Hashable1 Hashed Source # | |

Hashable a => Hashable1 (Either a) Source # | |

Hashable a1 => Hashable1 ((,) a1) Source # | |

Hashable1 (Proxy *) Source # | |

(Hashable a1, Hashable a2) => Hashable1 ((,,) a1 a2) Source # | |

Hashable a => Hashable1 (Const * a) Source # | |

(Hashable a1, Hashable a2, Hashable a3) => Hashable1 ((,,,) a1 a2 a3) Source # | |

(Hashable1 f, Hashable1 g) => Hashable1 (Sum * f g) Source # | |

(Hashable1 f, Hashable1 g) => Hashable1 (Product * f g) Source # | |

(Hashable a1, Hashable a2, Hashable a3, Hashable a4) => Hashable1 ((,,,,) a1 a2 a3 a4) Source # | |

(Hashable1 f, Hashable1 g) => Hashable1 (Compose * * f g) Source # | |

(Hashable a1, Hashable a2, Hashable a3, Hashable a4, Hashable a5) => Hashable1 ((,,,,,) a1 a2 a3 a4 a5) Source # | |

(Hashable a1, Hashable a2, Hashable a3, Hashable a4, Hashable a5, Hashable a6) => Hashable1 ((,,,,,,) a1 a2 a3 a4 a5 a6) Source # | |

class Hashable2 t where Source #

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

Lift a hashing function through the binary type constructor.

Hashable2 Either Source # | |

Hashable2 (,) Source # | |

Hashable a1 => Hashable2 ((,,) a1) Source # | |

Hashable2 (Const *) Source # | |

(Hashable a1, Hashable a2) => Hashable2 ((,,,) a1 a2) Source # | |

(Hashable a1, Hashable a2, Hashable a3) => Hashable2 ((,,,,) a1 a2 a3) Source # | |

(Hashable a1, Hashable a2, Hashable a3, Hashable a4) => Hashable2 ((,,,,,) a1 a2 a3 a4) Source # | |

(Hashable a1, Hashable a2, Hashable a3, Hashable a4, Hashable a5) => Hashable2 ((,,,,,,) a1 a2 a3 a4 a5) Source # | |

# Auxiliary Functions

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

Lift the `hashWithSalt`

function through the type constructor.

hashWithSalt1 = liftHashWithSalt hashWithSalt

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

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 Source #

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