There is currently a totally useless CPP in random:
#ifdef ENABLE_SPLITTABLEGEN
class SplittableGen g where
#endif
which hints at what I am about to suggest.
There are some pure RNGs like mersenne-twister for example, that are not splittable. Question is do we want to bring this distinction to the type level or not? I personally would like to avoid seeing such code:
instance RandomGen PureMT where
next = randomInt
split = error "System.Random.Mersenne.Pure: unable to split the mersenne twister"
There are four approaches I see that we can take:
- Follow the current path laid out in the code and simply remove the CPP pragmas:
class RandomGen g where
...
class RandomGen g => SplittableGen g where
split :: g -> (g, g)
- Disadvantage: breaks bunch of code in the wild that depends on
split.
- Advantage: none
- Similar to the above, but use default signatures and deprecation
class RandomGen g where
...
split :: g -> (g, g)
default split :: SplittableGen g => g -> (g, g)
split = splitGen
{-# DEPRECATED split "In favor of `splitGen`" #-}
class RandomGen g => SplittableGen g where
splitGen :: g -> (g, g)
- Disadvantage: eventually it will affect the user code
- Advantage: not a breaking change for RNG libraries
- Invert the dependency and create an
UnsplittableGen (name is up for a debate)
class NoSplitGen g where
...
genWord64 :: g -> (Word64, g)
class NoSplitGen g => RandomGen g where
split :: g -> (g, g)
- Advantage: will not break the user code, unless they are using a non-splittable RNG.
- Disadvantage: breaks current RNG libraries, which I think is OK, since they will need to be updated anyways.
- Not to worry about distinction between splittable/not-splittable and leave it as is:
- Advantages: less changes for everyone
- Disadvantages: partial code in the wild and hard to see the lack/presence of splitability property in th RNG
My favorite is the 3rd one. Any thoughts?
There is currently a totally useless
CPPinrandom:which hints at what I am about to suggest.
There are some pure RNGs like mersenne-twister for example, that are not splittable. Question is do we want to bring this distinction to the type level or not? I personally would like to avoid seeing such code:
There are four approaches I see that we can take:
split.UnsplittableGen(name is up for a debate)My favorite is the 3rd one. Any thoughts?