Proposal: Generalize the RandomGen and Random classes
aslatter at gmail.com
Wed Oct 6 19:09:22 EDT 2010
On Wed, Oct 6, 2010 at 5:53 PM, Thomas DuBuisson
<thomas.dubuisson at gmail.com> wrote:
> There has been precious few comments on this proposal (ending in 2
> days). Conversation has thus far been:
> Accept (1 - me)
> No - Random is H98 and changing it is not acceptable (2 - Milan, Yitz)
> Unknown Stance (2 - SPJ, Antonie Latter)
> Mostly I'm hoping for more comments. If you found the splittable
> debate of value then I'd imagine this aspect of Random would concern
> you too.
> In response to the idea that we can't or shouldn't change H98:
>> If those extensions
>> are all added to Haskell 2011 or whatever, then it could be considered.
> AFAIK, all accepted parts of Haskell standards are implemented FIRST
> (typically as a GHC extension or package) then considered for
> Haskell'. The Haskell2010 and Haskell98 packages, which you can
> import, can contain their own definition of System.Random - this could
> be static without stagnating all libraries that are mentioned in a
> Haskell standard.
>> I personally do not think it is worth to modify the Random module, which
>> dates back to at least Haskell 98. Maybe a new package on the Hackage?
> So because it is old we can't modify it? The point of changing the
> library is to benefit a broader portion of the community. We could
> stop any and all changes to package X and make a new package every
> time but this isn't a sufficient argument to me.
> If peoples only objections are compatibility then we can queue this
> change up with the next API breaking change, unless there will never
> again be such a change.
> On Tue, Sep 14, 2010 at 5:11 PM, Thomas DuBuisson
> <thomas.dubuisson at gmail.com> wrote:
>> RandomGen and Random classes assume generators produce Int values.
>> This is non-ideal as many high speed generators produce special values
>> (ex: doubles) or generic values (bit streams / bytestrings) that can
>> be converted directly to types easier than coercing to Int then to an
>> 'a' via the Random class.
>> See 4315  for the patch.
>> Period of discussion: Till October 8 (3.5 weeks, giving a little time
>> after ICFP for last minute debate)
>> Specifically, this proposal:
>> 1) Alters RandomGen:
>> class RandomGen g where
>> next :: g -> (Int, g)
>> genRange :: g -> (Int, Int)
>> class RandomGen g v | g -> v where
>> next :: g -> (v, g)
>> genRange :: g-> (v,v)
>> 2) Alters Random:
>> class Random a where
>> randomR :: RandomGen g => (a,a) -> g -> (a,g)
>> random :: RandomGen g => g -> (a, g)
>> randomRs :: RandomGen g => (a,a) -> g -> [a]
>> randoms :: RandomGen g => g -> [a]
>> randomRIO :: (a,a) -> IO a
>> randomIO :: IO a
>> class Random a where
>> randomR :: RandomGen g v => (a,a) -> g -> (a,g)
>> random :: RandomGen g v => g -> (a, g)
>> randomRs :: RandomGen g v => (a,a) -> g -> [a]
>> randoms :: RandomGen g v => g -> [a]
>> Additional Points of Debate
>> 1) Because random[R]IO can not be part of the new Random instance with
>> a sensible default, these have been moved to top-level functions:
>> randomRIO :: (Random a Int) => (a,a) -> IO a
>> randomIO :: (Random a Int) => IO a
>> Other options exist and I'm open to them. I'm just being upfront
>> about what the patch currently does.
>> 2) All pre-existing instances of "Random x" for some concrete 'x' have
>> been modified to be "instance Random x Int". As 'Int' was the
>> previous (hardcoded) default for RandomGen this is simply matching the
>> behavior. More instances are possible and probably make sense now.
>> Alternatively, one could argue for zero default instance as they can
>> collide with how a particular user wishes types to be coerced.
>> 3) Not-so-new extensions are used to enable these changes. Extensions
>> include MultiParamTypeClasses, FlexibleContexts, and FunDeps.
>> 4) A patch is included bumping the version from 1.0.0.x to 18.104.22.168.
>>  http://hackage.haskell.org/trac/ghc/ticket/4315
> Libraries mailing list
> Libraries at haskell.org
I guess the new class interface feels somehow off to me.
As a developer, I would now say: "The function requires a random
generator which exclusively produces Word16s" which I find oddly
specific, and lowers the chances of me being able to use a single
generator with disparately authored components without piles of
newtype shims (and who know what else).
Maybe a better solution would be for the RandomGen class to provide a
multitude of 'next' functions:
next :: g -> (Int, g)
nextInt :: g -> (Int, g)
nextInt8 :: g -> (Int8, g)
nextInt16 :: g -> (Int16, g)
nextInt32 :: g -> (Int32, g)
nextWord :: g -> (Word, g)
nextword8 :: g -> (Word8,g)
nextDouble :: g -> (Double, g)
The class methods other than 'next' would have a default
implementation equivalent to the above value's Random instance.
Then as a consumer of a RandomGen, I can ask for the values I want,
and the implementation of the RandomGen can provide efficiently what
And then as a downstream developer I can benchmark like crazy to find
the combination that works for me.
Plus, I don't think this requires additional extensions.
More information about the Libraries