Proposal: Generalize the RandomGen and Random classes

Antoine Latter 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:
> All,
> 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:
>
> Yitz:
>> 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.
>
> Milan:
>> 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.
>
> Cheers,
> Thomas
>
>
> On Tue, Sep 14, 2010 at 5:11 PM, Thomas DuBuisson
> <thomas.dubuisson at gmail.com> wrote:
>> Hello,
>> 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 [1] 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:
>>
>> from:
>>  class RandomGen g where
>>      next :: g -> (Int, g)
>>      genRange :: g -> (Int, Int)
>>
>> to
>>
>> class RandomGen g v | g -> v where
>>    next :: g -> (v, g)
>>    genRange :: g-> (v,v)
>>
>> 2) Alters Random:
>>
>> From:
>>
>> 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
>>
>> to
>>
>> 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 1.1.0.0.
>>
>> Cheers,
>> Thomas
>>
>> [1] http://hackage.haskell.org/trac/ghc/ticket/4315
>>
> _______________________________________________
> Libraries mailing list
> Libraries at haskell.org
> http://www.haskell.org/mailman/listinfo/libraries
>

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
it can.

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.

Antoine


More information about the Libraries mailing list