mini-1.7.0.0: src/Mini/Hash/Class.hs
{-# LANGUAGE FunctionalDependencies #-}
-- | Hash functions and hashable types
module Mini.Hash.Class (
-- * Classes
Hash (
hash,
digest
),
Hashable (
toBytes
),
) where
import Data.Bits (
FiniteBits,
finiteBitSize,
shiftR,
)
import Data.Int (
Int,
Int16,
Int32,
Int64,
Int8,
)
import Data.Word (
Word,
Word16,
Word32,
Word64,
Word8,
)
import Prelude (
Bool,
Char,
Enum,
Integral,
concatMap,
div,
fmap,
fromEnum,
fromIntegral,
iterate,
pure,
take,
($),
(.),
)
-- Classes
-- | The class of hash functions
class Hash h s d | h -> s d where
-- | Make a hash value from a hashable value and a seed
hash :: (Hashable a) => a -> s -> h
-- | Extract the digest of a hash value
digest :: h -> d
-- | Instances should use little-endian byte order
class Hashable a where
-- | Convert a hashable type to a sequence of bytes
toBytes :: a -> [Word8]
instance Hashable Bool where
toBytes = enumToBytes
instance Hashable Char where
toBytes = enumToBytes
instance Hashable Int where
toBytes = finiteBitsIntegralToBytes
instance Hashable Int8 where
toBytes = finiteBitsIntegralToBytes
instance Hashable Int16 where
toBytes = finiteBitsIntegralToBytes
instance Hashable Int32 where
toBytes = finiteBitsIntegralToBytes
instance Hashable Int64 where
toBytes = finiteBitsIntegralToBytes
instance Hashable Word where
toBytes = finiteBitsIntegralToBytes
instance Hashable Word8 where
toBytes = pure
instance Hashable Word16 where
toBytes = finiteBitsIntegralToBytes
instance Hashable Word32 where
toBytes = finiteBitsIntegralToBytes
instance Hashable Word64 where
toBytes = finiteBitsIntegralToBytes
instance (Hashable a) => Hashable [a] where
toBytes = concatMap toBytes
-- Helpers
enumToBytes :: (Enum a) => a -> [Word8]
enumToBytes = pure . fromIntegral . fromEnum
finiteBitsIntegralToBytes :: (FiniteBits a, Integral a) => a -> [Word8]
finiteBitsIntegralToBytes w =
take (finiteBitSize w `div` 8)
. fmap fromIntegral
$ iterate (`shiftR` 8) w