Class: Propr::Random

Inherits:
Object show all
Extended by:
Fr::Monad
Defined in:
lib/propr/random.rb

Class Method Summary collapse

Class Method Details

.bind(f, &g) ⇒ Object



40
41
42
43
44
45
46
47
48
# File 'lib/propr/random.rb', line 40

def bind(f, &g)
  lambda do |scale|
    value, scale, success = f.call(scale)

    success ?
      g.call(value).call(scale) :
      [value, scale, success]
  end
end

.eval(computation, scale = BigDecimal(1), retries = 0) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/propr/random.rb', line 16

def eval(computation, scale = BigDecimal(1), retries = 0)
  skipped = 0
  scale   = bound(scale)

  while true
    value, _, success = computation.call(scale)

    if success
      return value
    elsif (skipped += 1) > retries
      raise NoMoreTries, retries
    end
  end
end

.guard(*conditions) ⇒ Object

TODO: Make Random an instance of Functor and use Functor.guard?



54
55
56
57
58
# File 'lib/propr/random.rb', line 54

def guard(*conditions)
  lambda do |scale|
    [nil, scale, conditions.all?]
  end
end

.rand(limit = nil) ⇒ Object

Generate psuedo-random number normally distributed between 0 <= x < 1. This distribution is not weighted using ‘scale`.



83
84
85
86
87
88
89
90
91
# File 'lib/propr/random.rb', line 83

def rand(limit = nil)
  if not limit.nil? and limit <= 0
    raise InvalidArgument, "limit <= 0"
  end

  lambda do |scale|
    [Kernel.rand(limit), scale, true]
  end
end

.run(computation, scale = BigDecimal(1)) ⇒ Object

Evaluators



12
13
14
# File 'lib/propr/random.rb', line 12

def run(computation, scale = BigDecimal(1))
  computation.call(bound scale)
end

.scale(number, range, zero) ⇒ Object

When given two arguments, scales a numeric value around a given origin ‘zero`, using the current scale factor (0..1).



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/propr/random.rb', line 63

def scale(number, range, zero)
  if range.zero?
    # No scaling
    lambda do |scale|
      [number, scale, true]
    end
  else
    # Shrink range exponentially, and -1 + scale reduces the
    # rng_ to 0 when scale = 0, but rng_ = range when scale = 1.
    lambda do |scale|
      rng_ = (range ** scale) - 1 + scale
      pct  = (number - zero) / range
      [zero + rng_ * pct, scale, true]
    end
  end
end

.unit(value) ⇒ Object

Combinators



34
35
36
37
38
# File 'lib/propr/random.rb', line 34

def unit(value)
  lambda do |scale|
    [value, scale, true]
  end
end