Skip to content

Commit 915d3d7

Browse files
committed
Initial import of version 1.0.0
0 parents  commit 915d3d7

File tree

6 files changed

+186
-0
lines changed

6 files changed

+186
-0
lines changed

CHANGES

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
= Version 1.0.0, 2010-08-15 =
2+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3+
* Separating Hashable class to its own package
4+
from hashmap 1.0.0.3.

Data/Hashable.hs

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
{-# LANGUAGE ForeignFunctionInterface #-}
2+
3+
-----------------------------------------------------------------------------
4+
-- |
5+
-- Module : Data.Hash
6+
-- Copyright : (c) Milan Straka 2010
7+
-- License : BSD-style
8+
-- Maintainer : [email protected]
9+
-- Stability : provisional
10+
-- Portability : portable
11+
--
12+
-- 'Hashable' class for hashable types, with instances for basic types. The only
13+
-- function of this class is
14+
--
15+
-- @
16+
-- 'hash' :: Hashable h => h -> Int
17+
-- @
18+
--
19+
-- The 'hash' function should be as collision-free as possible, the probability
20+
-- of @'hash' a == 'hash' b@ should ideally be 1 over the number of representable
21+
-- values in an 'Int'.
22+
--
23+
-- Returning an 'Int' is a result of the 'Data.IntMap.IntMap' using 'Int' as
24+
-- a key, as inserting the hash values to the 'Data.IntMap.IntMap' was the
25+
-- purpose of creating this class.
26+
-----------------------------------------------------------------------------
27+
28+
module Data.Hashable ( Hashable(..)
29+
, combine
30+
) where
31+
32+
import Data.Bits
33+
import Data.Int
34+
import Data.Word
35+
import Data.List (foldl')
36+
import qualified Data.ByteString as B
37+
import qualified Data.ByteString.Internal as BInt
38+
import qualified Data.ByteString.Unsafe as BInt
39+
import qualified Data.ByteString.Lazy as BL
40+
import qualified Data.ByteString.Lazy.Internal as BLInt
41+
import Foreign.C
42+
43+
-- | The class containing a function 'hash' which computes the hash values of
44+
-- given value.
45+
class Hashable a where
46+
-- | The computed 'hash' value should be as collision-free as possible, the
47+
-- probability of @'hash' a == 'hash' b@ should ideally be 1 over the
48+
-- number of representable values in an 'Int'.
49+
hash :: a -> Int
50+
51+
-- | Combines two given hash values.
52+
combine :: Int -> Int -> Int
53+
combine h1 h2 = (h1 + h1 `shiftL` 5) `xor` h2
54+
55+
hashAndCombine :: Hashable h => Int -> h -> Int
56+
hashAndCombine acc h = acc `combine` hash h
57+
58+
instance Hashable () where hash _ = 0
59+
60+
instance Hashable Bool where hash x = case x of { True -> 1; False -> 0 }
61+
62+
instance Hashable Int where hash = id
63+
instance Hashable Int8 where hash = fromIntegral
64+
instance Hashable Int16 where hash = fromIntegral
65+
instance Hashable Int32 where hash = fromIntegral
66+
instance Hashable Int64 where hash = fromIntegral
67+
68+
instance Hashable Word where hash = fromIntegral
69+
instance Hashable Word8 where hash = fromIntegral
70+
instance Hashable Word16 where hash = fromIntegral
71+
instance Hashable Word32 where hash = fromIntegral
72+
instance Hashable Word64 where hash = fromIntegral
73+
74+
instance Hashable Char where hash = fromEnum
75+
76+
instance Hashable a => Hashable (Maybe a) where
77+
hash Nothing = 0
78+
hash (Just a) = 42 `combine` hash a
79+
80+
instance (Hashable a1, Hashable a2) => Hashable (a1, a2) where
81+
hash (a1, a2) = hash a1 `combine` hash a2
82+
83+
instance (Hashable a1, Hashable a2, Hashable a3) => Hashable (a1, a2, a3) where
84+
hash (a1, a2, a3) = hash a1 `combine` hash a2 `combine` hash a3
85+
86+
instance (Hashable a1, Hashable a2, Hashable a3, Hashable a4) => Hashable (a1, a2, a3, a4) where
87+
hash (a1, a2, a3, a4) = hash a1 `combine` hash a2 `combine` hash a3 `combine` hash a4
88+
89+
instance (Hashable a1, Hashable a2, Hashable a3, Hashable a4, Hashable a5)
90+
=> Hashable (a1, a2, a3, a4, a5) where
91+
hash (a1, a2, a3, a4, a5) =
92+
hash a1 `combine` hash a2 `combine` hash a3 `combine` hash a4 `combine` hash a5
93+
94+
instance (Hashable a1, Hashable a2, Hashable a3, Hashable a4, Hashable a5, Hashable a6)
95+
=> Hashable (a1, a2, a3, a4, a5, a6) where
96+
hash (a1, a2, a3, a4, a5, a6) =
97+
hash a1 `combine` hash a2 `combine` hash a3 `combine` hash a4 `combine` hash a5 `combine` hash a6
98+
99+
instance (Hashable a1, Hashable a2, Hashable a3, Hashable a4, Hashable a5, Hashable a6, Hashable a7)
100+
=> Hashable (a1, a2, a3, a4, a5, a6, a7) where
101+
hash (a1, a2, a3, a4, a5, a6, a7) =
102+
hash a1 `combine` hash a2 `combine` hash a3 `combine` hash a4 `combine` hash a5 `combine` hash a6 `combine` hash a7
103+
104+
instance Hashable a => Hashable [a] where
105+
{-# SPECIALIZE instance Hashable [Char] #-}
106+
hash = foldl' hashAndCombine 0
107+
108+
foreign import ccall unsafe hashByteString :: CString -> CInt -> IO CInt
109+
instance Hashable B.ByteString where
110+
hash bstr = fromIntegral $ BInt.inlinePerformIO $ BInt.unsafeUseAsCStringLen bstr $
111+
\(str, len) -> hashByteString str (fromIntegral len)
112+
113+
instance Hashable BL.ByteString where hash = BLInt.foldlChunks hashAndCombine 0

LICENSE

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Copyright Milan Straka 2010
2+
3+
All rights reserved.
4+
5+
Redistribution and use in source and binary forms, with or without
6+
modification, are permitted provided that the following conditions are met:
7+
8+
* Redistributions of source code must retain the above copyright
9+
notice, this list of conditions and the following disclaimer.
10+
11+
* Redistributions in binary form must reproduce the above
12+
copyright notice, this list of conditions and the following
13+
disclaimer in the documentation and/or other materials provided
14+
with the distribution.
15+
16+
* Neither the name of Milan Straka nor the names of other
17+
contributors may be used to endorse or promote products derived
18+
from this software without specific prior written permission.
19+
20+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Setup.hs

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env runhaskell
2+
import Distribution.Simple
3+
main = defaultMain

hashable.cabal

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Name: hashable
2+
Version: 1.0.0
3+
Synopsis: Class Hashable providing a hash method.
4+
Description: This package provides a class 'Hashable', which contains
5+
one method @'hash' :: 'Hashable' a => a -> 'Int'@, which
6+
returns the hash of the given element.
7+
.
8+
The instances for various integral types, 'String' and 'ByteString'
9+
are provided.
10+
Homepage: http://fox.auryn.cz/darcs/hashable
11+
License: BSD3
12+
License-file: LICENSE
13+
Author: Milan Straka
14+
Maintainer: [email protected]
15+
Stability: Provisional
16+
Category: Data
17+
Build-type: Simple
18+
Cabal-version: >=1.2
19+
Extra-source-files: CHANGES
20+
21+
22+
Library
23+
Exposed-modules: Data.Hashable
24+
Build-depends: base >= 4.0 && < 5,
25+
bytestring >= 0.9
26+
27+
C-sources: src/hashByteString.c

src/hashByteString.c

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
int hashByteString(const char* str, int len) {
2+
int hash = 0;
3+
4+
while (len--) {
5+
hash = (hash * 33) ^ *str++;
6+
}
7+
8+
return hash;
9+
}

0 commit comments

Comments
 (0)