trandomvars2.nim 975 B

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. discard """
  2. output: "11.0"
  3. """
  4. type
  5. # A random number generator
  6. Random = object
  7. random: proc(): float
  8. # A generic typeclass for a random var
  9. RandomVar[A] = concept x
  10. var rng: Random
  11. rng.sample(x) is A
  12. # A few concrete instances
  13. Uniform = object
  14. a, b: float
  15. ClosureVar[A] = object
  16. f: proc(rng: var Random): A
  17. # How to sample from various concrete instances
  18. proc sample(rng: var Random, u: Uniform): float = u.a + (u.b - u.a) * rng.random()
  19. proc sample[A](rng: var Random, c: ClosureVar[A]): A = c.f(rng)
  20. proc uniform(a, b: float): Uniform = Uniform(a: a, b: b)
  21. # How to lift a function on values to a function on random variables
  22. proc map[A, B](x: RandomVar[A], f: proc(a: A): B): ClosureVar[B] =
  23. proc inner(rng: var Random): B =
  24. f(rng.sample(x))
  25. result.f = inner
  26. import sugar
  27. proc fakeRandom(): Random =
  28. result.random = () => 0.5
  29. let x = uniform(1, 10).map((x: float) => 2 * x)
  30. var rng = fakeRandom()
  31. echo rng.sample(x)