diff --git a/src/Data/Random/Generics.hs b/src/Data/Random/Generics.hs index b856bf9..b06ae8c 100644 --- a/src/Data/Random/Generics.hs +++ b/src/Data/Random/Generics.hs @@ -1,4 +1,27 @@ -- | Generic Boltzmann samplers. +-- +-- Here, the words "/sampler/" and "/generator/" are used interchangeably. +-- +-- Given an algebraic datatype: +-- +-- > data A = A1 B C | A2 D +-- +-- a Boltzmann sampler is recursively defined by choosing a constructor with +-- some fixed distribution, and /independently/ generating values for the +-- corresponding fields with the same method. +-- +-- A key component is the aforementioned distribution, defined for every type +-- such that the resulting generator produces a finite value in the end. These +-- distributions are obtained from a precomputed object called /oracle/, which +-- we will not describe further here. +-- +-- Oracles depend on the target size of the generated data (except for singular +-- samplers), and can be fairly expensive to compute repeatedly, hence some of +-- the functions below attempt to avoid (re)computing too many of them even +-- when the required size changes. +-- +-- When these functions are specialized, oracles are memoized and will be +-- reused for different sizes. module Data.Random.Generics ( Size', @@ -52,9 +75,6 @@ import Data.Random.Generics.Internal.Types -- * Main functions -- $sized --- When these functions and their @_With@ counterparts below are specialized, --- the numerical /oracles/ are computed once and for all, so they can be reused --- for different sizes. -- -- === Suffixes -- @@ -81,7 +101,7 @@ import Data.Random.Generics.Internal.Types -- -- These generators filter out values whose sizes are not within some -- interval. In the first two sections, that interval is implicit: --- @[(1-'epsilon')*size, (1+'epsilon')*size]@, for @'epsilon' = 0.1@. +-- @[(1-'epsilon')*size', (1+'epsilon')*size']@, for @'epsilon' = 0.1@. -- -- The generator restarts as soon as it has produced more constructors than -- the upper bound, this strategy is called /ceiled rejection sampling/. diff --git a/src/Data/Random/Generics/Internal.hs b/src/Data/Random/Generics/Internal.hs index ed48a13..6f34b6c 100644 --- a/src/Data/Random/Generics/Internal.hs +++ b/src/Data/Random/Generics/Internal.hs @@ -18,6 +18,7 @@ data SG r = SG , runSmallG :: Points -> r } deriving Functor +-- | Number of pointing iterations. type Points = Int rangeSG :: SG r -> (Size, Maybe Size) @@ -67,7 +68,7 @@ makeR aliases a = fmap (flip runRejectT) (make aliases a) -- | The size of a value is its number of constructors. -- -- Here, however, the 'Size'' type is interpreted differently to make better --- use of QuickCheck's size parameter, provided by the 'Test.QuickCheck.sized' +-- use of QuickCheck's size parameter provided by the 'Test.QuickCheck.sized' -- combinator, so that we generate non-trivial data even at very small size -- values. -- @@ -85,8 +86,9 @@ makeR aliases a = fmap (flip runRejectT) (make aliases a) -- will target sizes close to @2 + delta@; -- the offset becomes less noticeable as @delta@ grows to infinity. -- --- For finite types with sizes in @[minSize, maxSize]@, the target --- expected size is obtained from a 'Size'' in @[0, 99]@ by an affine mapping. +-- For finite types with sizes in @[minSize, maxSize]@, the target expected +-- size is obtained by clamping a 'Size'' to @[0, 99]@ and applying an affine +-- mapping. type Size' = Int rescale :: SG r -> Size' -> Double diff --git a/src/Data/Random/Generics/Internal/Types.hs b/src/Data/Random/Generics/Internal/Types.hs index 30e6206..2c26fd7 100644 --- a/src/Data/Random/Generics/Internal/Types.hs +++ b/src/Data/Random/Generics/Internal/Types.hs @@ -151,7 +151,7 @@ class Monad m => MonadRandomLike m where incr :: m () incr = return () - -- | @doubleR@: generates values in @[0, upperBound)@. + -- | @doubleR upperBound@: generates values in @[0, upperBound]@. doubleR :: Double -> m Double -- | @integerR upperBound@: generates values in @[0, upperBound-1]@.