Proposal: Move 'split' into a separate class in System.Random

Bas van Dijk v.dijk.bas at gmail.com
Thu Oct 7 07:55:58 EDT 2010


On Thu, Oct 7, 2010 at 10:00 AM, Simon Peyton-Jones
<simonpj at microsoft.com> wrote:
> | > The "split" routine in the RandomGen seems to be a sore spot for some
> | > people and is perceived to have few users (even as a percentage of
> | > RandomGen users).  I propose:
> | >
> | > 1) Making a class "SplittableGen":
> | >
> | > class SplittableGen g where
> | >   split :: g -> (g, g)
> | >
> | > 2) (re)moving the "split" routine from the RandomGen class.
> | >
> | > See ticket 4314 [1] for the patch.
>
> The design, of having two classes, seems nearly right.  The nit is that surely RandomGen should be a superclass of SplittableGen?  I don't want to bloat my contexts too much.

+1

I did an analysys of the 254 direct reverse dependencies on random:

http://bifunctor.homelinux.net/~roel/cgi-bin/hackage-scripts/revdeps/random-1.0.0.2#direct

7 of those 254 packages use 'split' in test code only.

27 of those 254 packages use 'split' in production code.

11 of those 27 packages use 'split' polymorphically and have explicit
type signatures which need to change when 'split' is separated from
RandomGen.

Attached is the detailed analysis.

Regards,

Bas

P.S.
I'm thinking about creating a tool at the upcoming Hackaton that lists
the reverse dependencies of symbols. Because it's tedious and
error-prone to do this manually.
-------------- next part --------------
I did an analysys of the 254 direct reverse dependencies on random:

http://bifunctor.homelinux.net/~roel/cgi-bin/hackage-scripts/revdeps/random-1.0.0.2#direct

7 of those 254 packages use 'split' in test code only.

27 of those 254 packages use 'split' in production code.

11 of those 27 packages use split on a polymorphic random generator and have explicit type signatures which need to change when split is separated.


What follows is the detailed analysis: '!' indicates that split is used polymorphically and there is an explicit type signature.

./test-framework-quickcheck2-0.2.7/Test/Framework/Providers/QuickCheck2.hs:165:   (rnd1,rnd2) = split (randomSeed st)

./hstatistics-0.2.2.5/lib/Numeric/Statistics/Surrogate.hs:45:surrogate' g (n+1) f d = let (g',g'') = split g

./gloss-examples-1.1.1.0/Lifespan/World.hs:34:    	where	(genThis, genNext) = split gen
./gloss-examples-1.1.1.0/Lifespan/World.hs:35:          	(genA, genS)       = split genThis
./gloss-examples-1.1.1.0/Eden/World.hs:34:	= let	(genThis, genNext) = split gen
./gloss-examples-1.1.1.0/Eden/World.hs:35:          	(genA, genS)       = split genThis

./show-0.3.4/ShowQ.hs:93:      (rnd1,rnd2) = split rnd0

./KiCS-0.9.2/src/lib/Curry/Module/RandomExternal.hs.include:12:  (g1,g2) = split (mkStdGen (fromCurry seed))

./QuickCheck-2.3.0.2/Test/QuickCheck/Gen.hs:88:     let rnds rnd = rnd1 : rnds rnd2 where (rnd1,rnd2) = split rnd
./QuickCheck-2.3.0.2/Test/QuickCheck/Test.hs:241:  (rnd1,rnd2) = split (randomSeed st)

./testpack-2.0.1/src/Test/HUnit/Tools.hs:238:      where (rnd1,rnd2) = split (randomSeed st)

./topkata-0.2.3/Labygen.hs:39:       where (g', g'') = split g
./topkata-0.2.3/Labygen.hs:63:                  (g1, g2) = split g


! ./synthesizer-core-0.4.0.4/src/Synthesizer/State/Noise.hs:43:   let (g0,gr) = Rnd.split g
./synthesizer-core-0.4.0.4/src/Synthesizer/State/Noise.hs:44:       (g1,g2) = Rnd.split gr
! ./synthesizer-core-0.4.0.4/src/Synthesizer/State/NoiseCustom.hs:49:   let (g0,gr) = Rnd.split g
./synthesizer-core-0.4.0.4/src/Synthesizer/State/NoiseCustom.hs:50:       (g1,g2) = Rnd.split gr

./MagicHaskeller-0.8.5/MagicHaskeller/MyCheck.hs:35:    Gen m >>= k = Gen $ \n g -> case split g of (g1,g2) -> unGen (k (m n g1)) n g2
./MagicHaskeller-0.8.5/MagicHaskeller/MyCheck.hs:51:coarbitraryBool b (Gen f) = Gen $ \size stdgen -> f size $ case split stdgen of (g0,g1) -> if b then g0 else g1

./MagicHaskeller-0.8.5/MagicHaskeller/Classification.hs:41:arbs n stdgen  =  case split stdgen of

./MagicHaskeller-0.8.5/MagicHaskeller/Instantiate.hs:401:gens gen = case split gen of (g0,g1) -> g0 : gens g1

! ./mage-1.1.0/src/LevelGen.hs:153:        (lg, mg) = split g

! ./synthesizer-0.2.0.1/src/Synthesizer/State/Noise.hs:43:   let (g0,gr) = Rnd.split g
./synthesizer-0.2.0.1/src/Synthesizer/State/Noise.hs:44:       (g1,g2) = Rnd.split gr

./test-framework-quickcheck-0.2.7/Test/Framework/Providers/QuickCheck.hs:110:    (rnd1, rnd2) = split rnd0

! ./Haskelloids-0.1.1/src/Haskelloids.hs:263:  let (g',_) = split g
! ./Haskelloids-0.1.1/src/Haskelloids.hs:330:      (g'', _) = split g

! ./ideas-0.6/src/Domain/RelationAlgebra/Formula.hs:125:      | otherwise = let (g1, g2) = split g in g1 : makeRngs (n-1) g2

! ./local-search-0.0.3/Control/Search/Local.hs:139:simulatedAnnealingB p iTemp g = let (g' , g'' ) = split g

! ./comonad-random-0.1.2/Control/Comonad/Random.hs:72:                     ~(l, r) = split g

./hstest-0.0.1/hstest.hs:152:                             "| otherwise       = let (rnd1, rnd2) = System.Random.split rnd0 in ",

! ./SpaceInvaders-0.4.1/src/Main.hs:67:	        (g', g'') = split g
! ./SpaceInvaders-0.4.1/src/Main.hs:115:			where (g', g'') = split g

! ./rsagl-0.4.0.2/RSAGL/Math/Vector.lhs:267:    where (g_,g') = split g

! ./pkcs1-1.0.2/Codec/Encryption/PKCS1.hs:60:gens g = let (g1,g2) = split g in g1:gens g2

./pqc-0.2/Test/QuickCheck/Parallel.hs:121:      (rnd1,rnd2) = split rnd0

./simseq-0.0/src/UnfoldMut.hs:134:    (g,g') <- return . split =<< newStdGen
./simseq-0.0/src/UnfoldMut.hs:144:  | otherwise          = let (g1,g') = split g

./Barracuda-1.0.2/Barracuda/Distributor.hs:822:	let (_, obscMsg) = foldl (\(rand', msg) usr -> let (g1, g2) = System.Random.split rand' in (g2, obscureMessage' g1 msg usr)) (rand, Left (text, attachm
./Barracuda-1.0.2/Barracuda/ServerState.hs:155:initialState now gen v host addr = let (gen1, gen2) = Random.split gen in ServST

! ./hsgsom-0.1.0/Data/Datamining/Clustering/Gsom/Lattice.hs:60:  gs g = let (g1, g2) = split g in g1 : gs g2



Test code
=========

./storablevector-0.2.7/tests/QuickCheckUtils.hs:58:      (rnd1,rnd2) = split rnd0

./hylolib-1.3.0/src/HyLo/Test.hs:96:      (rnd1,rnd2) = split rnd0

./xmonad-bluetilebranch-0.9.1.4/tests/Properties.hs:1047:      (rnd1,rnd2) = split rnd0

./sexpr-0.2.1/Codec/Sexpr/Tests.hs:141:      (rnd1,rnd2) = split rnd0

./copilot-0.22/Language/Copilot/Tests/Random.hs:302:    let (oldG, newG) = split g in

./xmonad-0.9.1/tests/Properties.hs:1047:      (rnd1,rnd2) = split rnd0

./yi-0.6.2.4/tests/Driver.hs:71:--       (rnd1,rnd2) = split rnd0


More information about the Libraries mailing list