<div><div><div dir="auto">Zemyla! </div></div></div><div dir="auto"><br></div><div dir="auto">Yeah, absolutely agree that their pr has the wrong shape for monad random, which is why I’m confused by dominics pronouncement :), though its a great contrib.</div><div dir="auto"><br></div><div dir="auto">It should be (ignoring m being applicative vs monad)</div><div dir="auto">(For context, their design is roughly  ... MonadRandom m s g | m,g -> s ?  I’m typing on a phone so i might be restating it wrong ... :) )</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto">The *better* choice is </div><div dir="auto">Class PRNG g =>  MonadRandom m g | m-> g where ... </div><div dir="auto"><br></div><div dir="auto">And then their example instance  should be something like </div><div dir="auto"><br></div><div dir="auto">Newtype MWCT  m a = ... newtype wrapper around StateT m a threading an MWC indexed by the state token of the underlying PrimMonad</div><div dir="auto">(Or newtype MWCT s m a = .... stateT thing)</div><div dir="auto"><br></div><div dir="auto">Instance (PrimMonad m) => MonadRandom  (MWCT m) (MCWGen (PrimState m)) where ... </div><div dir="auto"><br></div><div dir="auto">Or something along those lines.  It absolutely shouldn’t be in the style of being on any PrimMonad, but part of a stack that provides that instance.  </div><div dir="auto"><br></div><div dir="auto">This is ignoring the freeze/thaw stuff which really is just “record and restore RNG state”, and i think is  an artifact of ther design choice in their PR. Which has a lot of great stuff I’m reviewing and poking at.</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto">Nothing is set in stone about deprecation and migration story, cause improving everything and making sure everyone has a zero pain/ or at least tolerable upgrade path is step zero.  (And making sure good stable interfaces persists is key! )</div><div dir="auto"><br></div><div dir="auto">I hope everyone is having a safe and healthy start to their summers, </div><div dir="auto"><br></div><div dir="auto">and I’m sorry for any confusions Dominics email about his collab Pr announcement has created.  But cest lie vie! Though sharing excitement about a great Pr is great! </div><div dir="auto"><br></div><div dir="auto">Stay well!</div><div dir="auto">-Carter </div><div dir="auto"><br></div><div dir="auto">On Tue, May 26, 2020 at 6:48 PM Zemyla <<a href="mailto:zemyla@gmail.com" target="_blank">zemyla@gmail.com</a>> wrote:<br></div><div><div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;padding-left:1ex;border-left-color:rgb(204,204,204)"><div dir="auto">And can you explain how to take an existing RNG and write it in this new format?</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, May 26, 2020, 15:54 David Feuer <<a href="mailto:david.feuer@gmail.com" target="_blank">david.feuer@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;padding-left:1ex;border-left-color:rgb(204,204,204)"><div dir="auto">Could you explain the reasoning behind the deprecations?</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, May 26, 2020, 6:00 AM  <<a href="mailto:dominic@steinitz.org" rel="noreferrer" target="_blank">dominic@steinitz.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;padding-left:1ex;border-left-color:rgb(204,204,204)"><div style="word-wrap:break-word;line-break:after-white-space"><p>Hello Libraries,</p><p>You may recall that following the blog <a href="https://alexey.kuleshevi.ch/blog/2019/12/21/random-benchmarks/" rel="noreferrer noreferrer" target="_blank">post</a> by @lehins, a group of us
(@curiousleo, @lehins and me) invited participation in <a href="https://mail.haskell.org/pipermail/libraries/2020-February/030261.html" rel="noreferrer noreferrer" target="_blank">February</a> to
take this work and apply it to improving the current <code style="font-family:monospace">random</code> library.</p><p>Our proximate goals were to fix <a href="https://github.com/haskell/random/issues/25" rel="noreferrer noreferrer" target="_blank">#25</a> (filed in 2015) and <a href="https://github.com/haskell/random/issues/51" rel="noreferrer noreferrer" target="_blank">#51</a> (filed in
2018). After a lot of discussion and experimentation, we have a
proposal that addresses both these issues and also: <a href="https://github.com/haskell/random/issues/26" rel="noreferrer noreferrer" target="_blank">#26</a>, <a href="https://github.com/haskell/random/issues/44" rel="noreferrer noreferrer" target="_blank">#44</a>, <a href="https://github.com/haskell/random/issues/53" rel="noreferrer noreferrer" target="_blank">#53</a>,
<a href="https://github.com/haskell/random/issues/55" rel="noreferrer noreferrer" target="_blank">#55</a>, <a href="https://github.com/haskell/random/issues/58" rel="noreferrer noreferrer" target="_blank">#58</a> and <a href="https://github.com/haskell/random/issues/59" rel="noreferrer noreferrer" target="_blank">#59</a>.</p><p>For backwards compatibility, the proposal retains the old style
classes and enhances them. Thus in 1.1 we have</p>

<pre style="font-family:monospace"><code style="font-family:monospace">class RandomGen g where
    next :: g -> (Int, g)
    genRange :: g -> (Int, Int)
    split :: g -> (g, g)
    {-# MINIMAL next, split #-}
</code></pre><p>and in 1.2 we have</p>

<pre style="font-family:monospace"><code style="font-family:monospace">class RandomGen g where
    next :: g -> (Int, g)
    genWord8 :: g -> (Word8, g)
    genWord16 :: g -> (Word16, g)
    genWord32 :: g -> (Word32, g)
    genWord64 :: g -> (Word64, g)
    genWord32R :: Word32 -> g -> (Word32, g)
    genWord64R :: Word64 -> g -> (Word64, g)
    genShortByteString :: Int
        -> g -> (Data.ByteString.Short.Internal.ShortByteString, g)
    genRange :: g -> (Int, Int)
    split :: g -> (g, g)
    {-# MINIMAL split, (genWord32 | genWord64 | next, genRange) #-}
</code></pre><p>and <code style="font-family:monospace">next</code> and <code style="font-family:monospace">genRange</code> are deprecated. This interface is what
allows the significantly faster performance as no longer is everything
forced to go via <code style="font-family:monospace">Integer</code>.</p><p>Several new interfaces are introduced and it is recommended that new
applications use these and, where feasible, existing applications
migrate to using them.</p><p>The major API addition in this PR is the definition of a new class <code style="font-family:monospace">MonadRandom</code>:</p>

<pre style="font-family:monospace"><code style="font-family:monospace">-- | 'MonadRandom' is an interface to monadic pseudo-random number generators.
class Monad m => MonadRandom g s m | g m -> s where
{-# MINIMAL freezeGen,thawGen,(uniformWord32|uniformWord64) #-}

    type Frozen g = (f :: Type) | f -> g
    freezeGen :: g s -> m (Frozen g)
    thawGen :: Frozen g -> m (g s)

    uniformWord32 :: g s -> m Word32 -- default implementation in terms of uniformWord64
    uniformWord64 :: g s -> m Word64 -- default implementation in terms of uniformWord32
    -- plus methods for other word sizes and for byte strings
    -- all have default implementations so the MINIMAL pragma holds
</code></pre><p>Conceptually, in <code style="font-family:monospace">MonadRandom g s m</code>, <code style="font-family:monospace">g s</code> is the type of the
generator, <code style="font-family:monospace">s</code> is the state type, and <code style="font-family:monospace">m</code> the underlying monad. Via
the functional dependency <code style="font-family:monospace">g m -> s</code>, the state type is determined by
the generator and monad.</p><p><code style="font-family:monospace">Frozen</code> is the type of the generator's state "at rest". It is defined
as an injective type family via <code style="font-family:monospace">f -> g</code>, so there is no ambiguity as
to which <code style="font-family:monospace">g</code> any <code style="font-family:monospace">Frozen g</code> belongs to.</p><p>This definition is generic enough to accommodate, for example, the
<code style="font-family:monospace">Gen</code> type from <code style="font-family:monospace">mwc-random</code>, which itself abstracts over the
underlying primitive monad and state token. This is the full instance
declaration (provided here as an example - this instance is not part
of <code style="font-family:monospace">random</code> as <code style="font-family:monospace">random</code> does not depend on <code style="font-family:monospace">mwc-random</code>):</p>

<pre style="font-family:monospace"><code style="font-family:monospace">instance (s ~ PrimState m, PrimMonad m) => MonadRandom MWC.Gen s m where
    type Frozen MWC.Gen = MWC.Seed
    freezeGen = MWC.save
    thawGen = MWC.restore

    uniformWord8 = MWC.uniform
    uniformWord16 = MWC.uniform
    uniformWord32 = MWC.uniform
    uniformWord64 = MWC.uniform
    uniformShortByteString n g = unsafeSTToPrim (genShortByteStringST n (MWC.uniform g))
</code></pre><p>Pure random number generators can also be made instances of this class
providing a uniform interface to both pure and stateful random number
generators. An instance for the standard number generator <code style="font-family:monospace">StdGen</code> is
provided.</p><p>The <code style="font-family:monospace">Random</code> typeclass has conceptually been split into <code style="font-family:monospace">Uniform</code> and
<code style="font-family:monospace">UniformRange</code>. The <code style="font-family:monospace">Random</code> typeclass is still included for backwards
compatibility. <code style="font-family:monospace">Uniform</code> is for types where it is possible to sample
from the type's entire domain; <code style="font-family:monospace">UniformRange</code> is for types where one
can sample from a specified range:</p>

<pre style="font-family:monospace"><code style="font-family:monospace">class Uniform a where
    uniformM :: MonadRandom g s m => g s -> m a

class UniformRange a where
    uniformRM :: MonadRandom g s m => (a, a) -> g s -> m a
</code></pre><p>The proposal is a breaking change but the changes are not very
intrusive and we have PRs ready for the affected downstream libraries:</p>

<ul>
<li>requires <code style="font-family:monospace">base</code> >= 4.10 (GHC-8.2)</li>
<li><code style="font-family:monospace">StdGen</code> is no longer an instance of <code style="font-family:monospace">Read</code></li>
<li><code style="font-family:monospace">randomIO</code> and <code style="font-family:monospace">randomRIO</code> were extracted from the <code style="font-family:monospace">Random</code> class
into separate functions</li>
</ul><p>In addition, there may be import clashes with new functions,
e.g. <code style="font-family:monospace">uniform</code> and <code style="font-family:monospace">uniformR</code>.</p><p>Further explanatory details may be found
<a href="https://github.com/idontgetoutmuch/random/blob/v1.2-release-notes/RELEASE-NOTES-v1.2.md#api-changes" rel="noreferrer noreferrer" target="_blank">here</a>
and the PR for the proposed new version is
<a href="https://github.com/haskell/random/pull/61" rel="noreferrer noreferrer" target="_blank">here</a>.</p><p>Here are some benchmarks run on a 3.1 GHz Intel Core i7. The full
benchmarks can be run using e.g. <code style="font-family:monospace">stack bench</code>. The benchmarks are
measured in milliseconds per 100,000 generations. In some cases, the
performance is over x1000(!) times better; the minimum performance
increase for the types listed below is more than x35.</p>

<pre style="font-family:monospace"><code style="font-family:monospace">| Name                    | Mean (1.1) | Mean (1.2) | Improvement|
| ----------------------- | ---------- | ---------- | ---------- |
| pure/random/Float       |         30 |       0.03 |        1038|
| pure/random/Double      |         52 |       0.03 |        1672|
| pure/random/Integer     |         43 |       0.33 |         131|
| pure/uniform/Word8      |         14 |       0.03 |         422|
| pure/uniform/Word16     |         13 |       0.03 |         375|
| pure/uniform/Word32     |         21 |       0.03 |         594|
| pure/uniform/Word64     |         42 |       0.03 |        1283|
| pure/uniform/Word       |         44 |       0.03 |        1491|
| pure/uniform/Int8       |         15 |       0.03 |         511|
| pure/uniform/Int16      |         15 |       0.03 |         507|
| pure/uniform/Int32      |         22 |       0.03 |         749|
| pure/uniform/Int64      |         44 |       0.03 |        1405|
| pure/uniform/Int        |         43 |       0.03 |        1512|
| pure/uniform/Char       |         17 |       0.49 |          35|
| pure/uniform/Bool       |         18 |       0.03 |         618|
| pure/uniform/CChar      |         14 |       0.03 |         485|
| pure/uniform/CSChar     |         14 |       0.03 |         455|
| pure/uniform/CUChar     |         13 |       0.03 |         448|
| pure/uniform/CShort     |         14 |       0.03 |         473|
| pure/uniform/CUShort    |         13 |       0.03 |         457|
| pure/uniform/CInt       |         21 |       0.03 |         737|
| pure/uniform/CUInt      |         21 |       0.03 |         742|
| pure/uniform/CLong      |         43 |       0.03 |        1544|
| pure/uniform/CULong     |         42 |       0.03 |        1460|
| pure/uniform/CPtrdiff   |         43 |       0.03 |        1494|
| pure/uniform/CSize      |         43 |       0.03 |        1475|
| pure/uniform/CWchar     |         22 |       0.03 |         785|
| pure/uniform/CSigAtomic |         21 |       0.03 |         749|
| pure/uniform/CLLong     |         43 |       0.03 |        1554|
| pure/uniform/CULLong    |         42 |       0.03 |        1505|
| pure/uniform/CIntPtr    |         43 |       0.03 |        1476|
| pure/uniform/CUIntPtr   |         42 |       0.03 |        1463|
| pure/uniform/CIntMax    |         43 |       0.03 |        1535|
| pure/uniform/CUIntMax   |         42 |       0.03 |        1493|
</code></pre><br><br><div>
<div dir="auto" style="word-wrap:break-word;line-break:after-white-space"><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;color:rgb(0,0,0)">Dominic Steinitz</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;color:rgb(0,0,0)"><a href="mailto:dominic@steinitz.org" rel="noreferrer noreferrer" style="font-family:Helvetica" target="_blank">dominic@steinitz.org</a></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;color:rgb(0,0,0)"><a href="http://idontgetoutmuch.org" rel="noreferrer noreferrer" style="font-family:Helvetica" target="_blank">http://idontgetoutmuch.org</a></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;color:rgb(0,0,0)">Twitter: @idontgetoutmuch</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;color:rgb(0,0,0)"><br></div><br></div><br>
</div>
<br></div>_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org" rel="noreferrer noreferrer" target="_blank">Libraries@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer noreferrer noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a><br>
</blockquote></div>
_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org" rel="noreferrer" target="_blank">Libraries@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a><br>
</blockquote></div>
_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org" target="_blank">Libraries@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a><br>
</blockquote></div></div>
</div>