Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error with generic concepts #5084

Closed
andreaferretti opened this issue Dec 2, 2016 · 1 comment
Closed

Error with generic concepts #5084

andreaferretti opened this issue Dec 2, 2016 · 1 comment
Labels

Comments

@andreaferretti
Copy link
Collaborator

For a minimal example, let me define a fake RNG, together with a function to get random float values from it:

type RNG = object

proc random(rng: var RNG): float = 1.0

Now, I define a RandomVar[A] as something that is able, given a RNG, to sample random instances of A. As a few concrete instances, I consider a constant, a uniform distribution, and a closure. I also define constructors for these types, as well as sample functions to make sure that they are instances of RandomVar[A]:

type
  RandomVar[A] = concept x
    var rng: RNG
    x.sample(rng) is A
  Constant[A] = object
    value: A
  Uniform = object
    a, b: float
  ClosureVar[A] = proc(rng: var RNG): A

proc sample[A](rng: var RNG, c: Constant[A]): A = c.value

proc sample(rng: var RNG, u: Uniform): float = u.a + (u.b - u.a) * rng.random()

proc sample[A](rng: var RNG, c: ClosureVar[A]): A = c(rng)

proc constant[A](a: A): Constant[A] = Constant[A](value: a)

proc uniform(a, b: float): Uniform = Uniform(a: a, b: b)

What I am trying to do is define operators on random variables. Here is a function that will lift a function A => B to a function RandomVar[A] => RandomVar[B]:

proc lift1[A, B](f: proc(a: A): B, r: RandomVar[A]): ClosureVar[B] =
  proc inner(rng: var RNG): B = f(rng.sample(r))

  return inner

When I try to use lift1 I get a compile time error:

when isMainModule:
  proc sq(x: float): float = x * x

  let
    c = constant(3)
    u = uniform(2, 18)
    t = lift1[float, float](sq, u)

  var rng: RNG

  echo(c is RandomVar[int])
  echo(u is RandomVar[float])
  # echo(t is RandomVar[float])
  echo rng.sample(c)
  echo rng.sample(u)
  # echo rng.sample(t)

The line t = lift1[float, float](sq, u) fails with

Error: type mismatch: got (RNG, RandomVar[system.float])
but expected one of: 
proc sample[A](rng: var RNG; c: Constant[A]): A
proc sample[A](rng: var RNG; c: ClosureVar[A]): A
proc sample(rng: var RNG; u: Uniform): float

To reproduce the error more easily, here is the whole thing:

type RNG = object

proc random(rng: var RNG): float = 1.0

type
  RandomVar[A] = concept x
    var rng: RNG
    x.sample(rng) is A
  Constant[A] = object
    value: A
  Uniform = object
    a, b: float
  ClosureVar[A] = proc(rng: var RNG): A

proc sample[A](rng: var RNG, c: Constant[A]): A = c.value

proc sample(rng: var RNG, u: Uniform): float = u.a + (u.b - u.a) * rng.random()

proc sample[A](rng: var RNG, c: ClosureVar[A]): A = c(rng)

proc constant[A](a: A): Constant[A] = Constant[A](value: a)

proc uniform(a, b: float): Uniform = Uniform(a: a, b: b)


proc lift1[A, B](f: proc(a: A): B, r: RandomVar[A]): ClosureVar[B] =
  proc inner(rng: var RNG): B = f(rng.sample(r))

  return inner

when isMainModule:
  proc sq(x: float): float = x * x

  let
    c = constant(3)
    u = uniform(2, 18)
    t = lift1[float, float](sq, u)

  var rng: RNG

  echo(c is RandomVar[int])
  echo(u is RandomVar[float])
  # echo(t is RandomVar[float])
  echo rng.sample(c)
  echo rng.sample(u)
  # echo rng.sample(t)
@branpk
Copy link
Contributor

branpk commented Jan 10, 2017

Well the type error is because you have a typo in your concept:

type
  RandomVar[A] = concept x
    var rng: RNG
    x.sample(rng) is A

The x.sample(rng) is A should be rng.sample(x) is A.

As fate would have it, fixing this crashes the compiler.

@Araq Araq added the Concepts label Feb 2, 2017
zah added a commit that referenced this issue Jun 19, 2017
@Araq Araq closed this as completed in 90e82f8 Jun 20, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants