diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 59add90a27..6084e11c02 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -628,9 +628,9 @@ proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} = else: result = isNone -proc matchUserTypeClass*(c: PContext, m: var TCandidate, - ff, a: PType): PType = +proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType = var + c = m.c typeClass = ff.skipTypes({tyUserTypeClassInst}) body = typeClass.n[3] matchedConceptContext: TMatchedConcept @@ -661,6 +661,9 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate, typeParamName = ff.base.sons[i-1].sym.name typ = ff.sons[i] param: PSym + alreadyBound = PType(idTableGet(m.bindings, typ)) + + if alreadyBound != nil: typ = alreadyBound template paramSym(kind): untyped = newSym(kind, typeParamName, typeClass.sym, typeClass.sym.info) @@ -1490,7 +1493,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, else: considerPreviousT: if aOrig == f: return isEqual - var matched = matchUserTypeClass(c.c, c, f, aOrig) + var matched = matchUserTypeClass(c, f, aOrig) if matched != nil: bindConcreteTypeToUserTypeClass(matched, a) if doBind: put(c, f, matched) diff --git a/tests/concepts/trandomvars.nim b/tests/concepts/trandomvars.nim new file mode 100644 index 0000000000..db41aa9019 --- /dev/null +++ b/tests/concepts/trandomvars.nim @@ -0,0 +1,61 @@ +discard """ +output: ''' +true +true +true +3 +18.0 +324.0 +''' +""" + +type RNG = object + +proc random(rng: var RNG): float = 1.0 + +type + RandomVar[A] = concept x + var rng: RNG + rng.sample(x) 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(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) +