Hand-rolled Random Number generator

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
module Data.Random where

import Random             -- or 'import System.Random'
import Data.List

import Algorithmic.Automata.Cellular  -- http://lpaste.net/107206

import Control.Comonad                -- http://lpaste.net/107661

import Data.Universe                  -- http://lpaste.net/108632

{-- 

Okay, now I get to write my own random number generator. Wheee!

 --}

data RNG = RND (U Bool) Int

instance Show RNG where
   show (RND (U a b c) bits) = "RNG ["
      ++ (showBits (reverse (take bits a))) ++ " < " 
      ++ show (showBit b) ++ " > "
      ++ (showBits (take bits c)) ++ "]"
      where showBits bits = map showBit bits
            showBit bit = if bit then '1' else '0'

mkRNG :: Int -> Integer -> RNG
mkRNG precision slt = RND (U (salt slt) True (salt slt)) precision

{--

So, for example: 

> mkRNG 10 324789235687
RNG [1010110010 < '1' > 0100110101]
*Data.Random> next it
(707226,RNG [1010101110 < '1' > 0111100101])
*Data.Random> next $ snd it
(703218,RNG [1010101000 < '1' > 0100011101])
*Data.Random> next $ snd it
(696974,RNG [0010101101 < '1' > 0110110001])
*Data.Random> next $ snd it
(177880,RNG [0110101001 < '0' > 0100101011])
*Data.Random> next $ snd it
(435349,RNG [1100101111 < '1' > 1111101010])

 --}

salt :: Integer -> [Bool]
salt sommat = (unfoldr (\val -> if val <= 0 then Nothing
                                else let (a, b) = val `divMod` 2
                                     in  Just (b == 0, a - b))
                       sommat) ++ repeat False

instance RandomGen RNG where
   next (RND d bits) = (x d, RND (d =>> rule30) bits)
       -- geddit? xD, x d, XD, geddit? ;)
      where x d = toInt $ toList (-1 * bits) bits d
   split (RND d bits) = (RND (a d) bits, RND (b d) bits)
      where a (U a b c) = U (repeat False) b c
            b (U a b c) = U a b (repeat False)

{--

TODO: So, RNG is a 'roll your own' random number generator. I suppose it
SHOULD be seeded. ... Yes, it surely does. ... Okay, adding it.

DONE

 --}
22:10: Warning: Redundant bracket
Found:
(showBits (reverse (take bits a))) ++
" < " ++
show (showBit b) ++ " > " ++ (showBits (take bits c)) ++ "]"
Why not:
showBits (reverse (take bits a)) ++
" < " ++
show (showBit b) ++ " > " ++ (showBits (take bits c)) ++ "]"
24:10: Warning: Redundant bracket
Found:
(showBits (take bits c)) ++ "]"
Why not:
showBits (take bits c) ++ "]"
25:13: Error: Eta reduce
Found:
showBits bits = map showBit bits
Why not:
showBits = map showBit
51:15: Warning: Redundant bracket
Found:
(unfoldr
(\ val ->
if val <= 0 then Nothing else
let (a, b) = val `divMod` 2 in Just (b == 0, a - b))
sommat)
++ repeat False
Why not:
unfoldr
(\ val ->
if val <= 0 then Nothing else
let (a, b) = val `divMod` 2 in Just (b == 0, a - b))
sommat
++ repeat False