mini-2.2.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.List.NonEmpty (
NonEmpty (
(:|)
),
)
import Data.Word (
Word,
Word16,
Word32,
Word64,
Word8,
)
import Mini.Data.Array (
Array,
)
import qualified Mini.String.UTF8 as UTF8 (
encode,
)
import Prelude (
Bool,
Char,
Either (
Left,
Right
),
Enum,
Integral,
Maybe (
Just,
Nothing
),
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 = UTF8.encode
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 (Maybe a) where
toBytes Nothing = []
toBytes (Just a) = toBytes a
instance (Hashable a, Hashable b) => Hashable (Either a b) where
toBytes (Left a) = toBytes a
toBytes (Right b) = toBytes b
instance (Hashable a, Hashable b) => Hashable (a, b) where
toBytes (a, b) = toBytes a <> toBytes b
instance (Hashable a) => Hashable [a] where
toBytes = concatMap toBytes
instance (Hashable a) => Hashable (NonEmpty a) where
toBytes (a :| as) = toBytes a <> toBytes as
instance (Hashable a) => Hashable (Array i 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