Proposal: Generalize the RandomGen and Random classes

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

Hi Thomas,
On Tue, Sep 14, 2010 at 7:11 PM, Thomas DuBuisson
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.
So when I write a Random instance, under this proposal I write it against a class of RandomGen instances, whereas in the current world I am able to plug and Random instantiated type up with any RandomGen instantiated type. Do you anticipate a common choice for the type 'v' (other than Int, of course)? When I write my Random instance against this new class, am I really targeting one particular good random generator?
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.
How many packages on Hackage provide instances for the Random class? How many of these packages provide an upper-bound on the random package in their package description? Do you also propose added an entry in the hackage preferred-versions file[1] for the 'random' package? What I'm truly getting at is: what will this break and how will we handle the breakage under this proposal? Thanks, Antoine [1] http://www.mail-archive.com/cabal-devel@haskell.org/msg03959.html

On Wed, Sep 15, 2010 at 4:33 AM, Antoine Latter
How many packages on Hackage provide instances for the Random class?
Around 30 packages. See the attachment (a grep for "instance Random " on all direct reverse dependencies of 'random') for details. Regards, Bas P.S. I'm not sure yet about this proposal.

On 7 October 2010 23:18, Bas van Dijk
On Wed, Sep 15, 2010 at 4:33 AM, Antoine Latter
wrote: How many packages on Hackage provide instances for the Random class?
Around 30 packages.
See the attachment (a grep for "instance Random " on all direct reverse dependencies of 'random') for details.
A lot of those can be removed if Random has instances for Word* by default. Is there any reason they aren't already instances?
P.S. I'm not sure yet about this proposal.
Agreed. -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com

Hi, as far as I know, a random generator usually creates an int or a sequence of bits, right? Or do you have some specific random generators in mind? 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? Cheers, Milan
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@haskell.org http://www.haskell.org/mailman/listinfo/libraries

| class RandomGen g v | g -> v where | next :: g -> (v, g) | genRange :: g-> (v,v) Or, perhaps nicer, class RandomGen g where type RandomVal g next :: g -> (RandomVal g, g) genRange :: g -> (RandomVal g, RandomVal g) where "RandomVal g" means "the type of values produced by generator g". Simon

Thomas DuBuisson wrote:
3) Not-so-new extensions are used to enable these changes. Extensions include MultiParamTypeClasses, FlexibleContexts, and FunDeps.
This package is a basic part of Haskell, so it should conform to the standard. So I think this proposal is premature. If those extensions are all added to Haskell 2011 or whatever, then it could be considered. In the meantime, these are great ideas. It would be wonderful to have alternatives to random on Hackage that implement these and other enhancements. Thanks, Yitz

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
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

On Wed, Oct 6, 2010 at 5:53 PM, Thomas DuBuisson
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
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
_______________________________________________ Libraries mailing list Libraries@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

On Wed, Oct 6, 2010 at 6:09 PM, Antoine Latter
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
All of this is predicated on specializing the random-data-consumer to the random-data-producer being a significant performance win. Antoine

On Wed, Oct 6, 2010 at 7:10 PM, Antoine Latter
All of this is predicated on specializing the random-data-consumer to the random-data-producer being a significant performance win.
I am very skeptical that this is the case. I'd like to see a demonstration that specializing an RNG in this way is helpful (and that implementing / sensibly defaulting the missing methods actively gets in the way of this specialization). -Jan-Willem Maessen

All, In summary to this proposal, I think the community agrees it is too "cludgy". Perhaps people would have agreed on one of SPJs suggested designs [1], so I might make another proposal when I again have time. I'll mark the associated bug as closed, or whatever seems closest to 'reject'. Cheers, Thomas [1]
class RandomGen g where type GenVal g :: * next :: g -> (GenVal g, g)
class Random a v where randoms :: forall g. (RandomGen g, v ~ GenVal g) => g -> [a]
or
class RandomGen g where nextInt :: g -> (Int, g) nextByteString :: g -> (ByteString, g)

Hi,
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.
I do not object to a change, but as I said in the paragraph above the cited one, I do not see much benefit (so I consider breaking this code a bigger issue than gain from accepting it). Let me repeat my question: - what other types than Int do you have in mind? (also asked by Antoine Latter) It seems to me that bits can be trivially converted to Ints. Personally I also do not like Functional dependencies very much. I would rather be in favor of type families, as SPJ suggested. Cheers, Milan
Cheers, Thomas
On Tue, Sep 14, 2010 at 5:11 PM, Thomas DuBuisson
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

2010/10/6 Milan Straka
I do not object to a change, but as I said in the paragraph above the cited one, I do not see much benefit (so I consider breaking this code a bigger issue than gain from accepting it).
Sorry for the misrepresentation.
Let me repeat my question: - what other types than Int do you have in mind? (also asked by Antoine Latter) It seems to me that bits can be trivially converted to Ints.
I like the idea of generating bytestrings - this is evidenced by my API in Crypto.Random. At the same time, I can understand not making "random" depend on "bytestring" being important, which is why I made the class flexible in generated type (and not a bunch of "nextTypeX" routines as Antoine brought up). Other packages seem to generate Double and do so with speed. One can imagine a world where bytestring falls out of favor (PackedString will never die!) for the next packaging.
Personally I also do not like Functional dependencies very much. I would rather be in favor of type families, as SPJ suggested.
I don't have a dog in this fight, aside from Mark Jones controlling some of my grades, pay check and ability to advance in my academic career ;-). Seriously, I'll go with whatever. I thought FDs were still the thing for base libraries but if they aren't then I'll make a TF based patch. Antione said:
I guess the new class interface feels somehow off to me. ... proposes "nextInt32", "nextDouble", etc ...
I'm all for considering other interfaces, but I can't figure out how to make a clean interface that allows arbitrary types to be generated. What happens when I can generate ByteString? And how about Vector? We don't want the "random" package depending on these others and we dont' want users to 1) not user Random when it should still make sense 2) Use random in some ugly manner such as: rand = pack . gen when gen = unpack . backendGen. Cheers, Thomas

| > 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.
On looking at this again, I think the proposed API looks over-elaborate. Surely there must be a better way?
The current design (trimmed down) is like this:
class RandomGen g where
next :: g -> (Int, g)
class Random a where
randoms :: forall g. RandomGen g => g -> [a]
The logic is
* RandomGen is a way to get a supply of bits, here expressed as Int
Maybe the class should have been called (BitSupply g)
* Random is a way to turn a supply of bits into values of some arbitrary type a
Notice that a single instance of Random, say Random Integer, will work for
*arbitrary* generators g.
In the proposal each instance of RandomGen produces values of a single type 'v', functionally dependent on the generator type 'g':
class RandomGen g v | g -> v where
next :: g -> (v, g)
Then there's a conversion from the fixed-but-unknown type 'v' to an arbitrary type 'a':
class Random a v where
randoms :: forall g. RandomGen g v => g -> [a]
The original message proposing the change omitted the 'v' parameter from Random. Yes, it's complicated: the intermediate type 'v' is really just a bit-supply.
Now we need to make a new instance of Random for each bit-supply type 'v'. It's not *so* bad: we expect to have
* Lots of generators g
* Lots of result types a
* Rather few bit-supply types v; perhaps just Int and Bytestring?
We need a Random instance for each (a,v) pair.
The types are a bit subtle. Look at the type of
randoms :: (Random a v, RandomGen g v) => g -> [a]
A call site presumably fixes, g and a; then the functional dependency fixes v; then we can find instances for (Random a v, RandomGen g v).
In type-function form it would have to look like this:
class RandomGen g where
type GenVal g :: *
next :: g -> (GenVal g, g)
class Random a v where
randoms :: forall g. (RandomGen g, v ~ GenVal g) => g -> [a]
which makes the functional dependency explicit.
It's not a silly design. But it's a rather abstract one, and there's always a danger of going overboard with abstraction in Haskell :-).
How many bit-supply types v do you want? Would it be enough to ask generators to generate all of them? Antoine suggested this:
class RandomGen g where
nextInt :: g -> (Int, g)
nextByteString :: g -> (ByteString, g)
But unlike Antoine's suggestion, I think we only need a tiny handful of bit supply types, because the Random class does the impedence matching to other types.
Simon
| -----Original Message-----
| From: libraries-bounces@haskell.org [mailto:libraries-bounces@haskell.org] On
| Behalf Of Thomas DuBuisson
| Sent: 06 October 2010 23:53
| To: Haskell Libraries; Milan Straka; Yitz
| Subject: Re: Proposal: Generalize the RandomGen and Random classes
|
| 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
|

If the random library is changed to use the language extensions MultiParamTypeClasses and FunctionalDependencies, then it will be removed from the Haskell 2011 standard libraries, since there is no proposal for Haskell 2011 to adopt either of those extensions.
Regards,
Malcolm
On 07 Oct, 2010,at 09:35 AM, Simon Peyton-Jones

On Thu, Oct 07, 2010 at 09:43:28AM +0000, Malcolm Wallace wrote:
If the random library is changed to use the language extensions MultiParamTypeClasses and FunctionalDependencies, then it will be removed from the Haskell 2011 standard libraries, since there is no proposal for Haskell 2011 to adopt either of those extensions.
The random library isn't in the H2010 standard libraries. Thanks Ian

Simon Peyton-Jones schrieb:
| > 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.
On looking at this again, I think the proposed API looks over-elaborate. Surely there must be a better way?
The current design (trimmed down) is like this: class RandomGen g where next :: g -> (Int, g)
class Random a where randoms :: forall g. RandomGen g => g -> [a]
The logic is * RandomGen is a way to get a supply of bits, here expressed as Int Maybe the class should have been called (BitSupply g)
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?

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. Cheers, Thomas

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.
participants (12)
-
Antoine Latter
-
Bas van Dijk
-
Henning Thielemann
-
Henning Thielemann
-
Ian Lynagh
-
Ivan Lazar Miljenovic
-
Jan-Willem Maessen
-
malcolm.wallace
-
Milan Straka
-
Simon Peyton-Jones
-
Thomas DuBuisson
-
Yitzchak Gale