aboutsummaryrefslogtreecommitdiff
path: root/ch26/26_a_1/26_a_1.hs
blob: 3b497a2d6b35427461fe29f232c191baa9a06f1d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
-- Our use of genericLength in easyList will cause our function to loop
-- infinitely if we supply an infinite list. Fix this.


-- It is not possible to decide whether a list has been defined as infinite. For
-- this, there would have to be some reflection capabilities in the
-- language. Only a finite limit on the list max. length can be set and checked.


-- I was compiling the code of this chapter by 'cabal build'. There were some
-- warnings and errors. I have fixed only the errors.
--
--   - in BloomFilter/Hash.hs, a part of the import statement for CSize had to
--     be changed from '(CSize)' to '(CSize(..))' to import the data
--     constructor, not only the type constructor.
--
--   - in BloomFilter.hs in the fromList function, the 'B hash . runSTUArray $'
--     had to be changed to 'B hash $ runSTUArray $' for the code to compile.


-- For testing, I was loading the code into ghci. For it to be able to find
-- symbols from the lookup3.o file, I needed to convert it to a shared library
--
--   gcc ./dist-newstyle/build/x86_64-linux/ghc-9.6.7/rwh-bloomfilter-0.1/build/cbits/lookup3.o -shared -o liblookup3.so
--
-- and load the shared library on start of ghci
--
--   stack ghci --ghci-options "-L$(pwd) -llookup3"


import BloomFilter.Easy
import BloomFilter.Hash (Hashable, doubleHash)
import Data.List (genericLength)
import qualified BloomFilter as B

-- Helper function for forcing evaluation of the easyList and fixedEasyList
-- return value
easyListLength l =
  case l of
    Left err -> error err
    Right b  -> BloomFilter.Easy.length b

-- Short length for more illustrative testing
maxLength = 10

fixedEasyList errRate values =
  if isLongerThan values maxLength
  then
    Left $ "List longer than " ++ (show maxLength) ++ " elements"
  else
    case suggestSizing (genericLength values) errRate of
      Left err            -> Left err
      Right (bits,hashes) -> Right filt
        where filt = B.fromList (doubleHash hashes) bits values

isLongerThan values max = isLongerThan' values 0 max
  where
    isLongerThan' []     l max = False
    isLongerThan' (v:vs) l max
      | (l + 1) > max = True
      | otherwise     = isLongerThan' vs (l + 1) max


-- ghci> :l 26_a_1.hs
-- [1 of 7] Compiling BloomFilter.Hash ( BloomFilter/Hash.hs, interpreted )
--   ... <omitted warnings here>
-- [2 of 7] Compiling BloomFilter.Internal ( BloomFilter/Internal.hs, interpreted )
-- [3 of 7] Compiling BloomFilter.Mutable ( BloomFilter/Mutable.hs, interpreted )
-- [4 of 7] Compiling BloomFilter      ( BloomFilter.hs, interpreted )
-- [5 of 7] Compiling BloomFilter.Easy ( BloomFilter/Easy.hs, interpreted )
-- [6 of 7] Compiling Main             ( 26_a_1.hs, interpreted )
-- Ok, six modules loaded.

-- ghci> l = easyList 0.2 [1..]
-- ghci> easyListLength l
-- *** Exception: stack overflow

-- ghci> l = fixedEasyList 0.2 [1..]
-- ghci> easyListLength l
-- *** Exception: List longer than 10 elements
-- CallStack (from HasCallStack):
--   error, called at 26_a_1.hs:40:17 in main:Main

-- ghci> l = fixedEasyList 0.2 [1..10]
-- ghci> easyListLength l
-- 34