
On Sun, 10 Oct 2010, Thomas DuBuisson wrote:
Couldn't we just have
class RandomGen g where next :: g -> (Bool, g)
where the generator can be internally based on Word32, Word64 or whatever is appropriate? Then the Random methods compose the bits to Ints, Integers, Word16, Float etc. but some optimizer rules take care of that the bit representation is actually not needed in common cases?
I think you're dreaming of an imaginary optimizer of supreme power. I don't see how RULES can ever get me from "next :: g -> (Bool, g)" to an efficient "nonce :: g -> (ByteString, g)". Obviously I would be thrilled to be proven wrong.
Given next :: RandomGen g => g -> (Bool, g) it is straightforward to generically implement nextWord8 :: RandomGen g => g -> (Word8, g) nextWord16 :: RandomGen g => g -> (Word16, g) Now, say I want to program a RandomGen that is based on Word16. I implement myNextWord16 :: MyGen -> (Word16, MyGen) and on top of it - so to say as fall-back - I implement myNextBit :: MyGen -> (Bool, MyGen) Now a rule {-# RULES nextWord16 = myNextWord16 #-} prevents us from actually going the long way from myNextWord16 to myNextBit to 'next' and back to 'nextWord16'. I don't know, how Random ByteString is implemented, but if it is implemented efficiently in terms of a Word8 generator, it could also be implemented quite efficiently on MyGen. However, a problem is, that MyGen must handle interleaved calls of Bit access (nextBit) and Word16 access (nextWord16). Thus it must maintain a bit counter that says which portions of the current Word16 have already been shipped and it must contain bit shuffling code. Hm, not optimal, I admit.