def find_instance(self, mono): '''find typeclass instance matching mono''' tool.debug('finding instance of:', self.name, mono.show()) # print('finding instance of:', self.name, 'for:', mono.show()) t = type(mono) matches = [] for scheme, instance in self.instances.items(): # TODO what about depth ? fresh = hm.instantiate( scheme ) try: # note: we unify in a fresh union_find hm.unify(tool.UnionFind(), fresh, mono) matches.append( (scheme, instance) ) except error.Type: pass if not matches: raise error.Type('typeclass {0} has no instance for type {1}' .format( self.name, mono.show() )) if len(matches) > 1: raise error.Type('ambiguous {0} instances for {1}'.format(self.name, mono.show())) return matches[0]
def unify(uf, a, b): a = uf.find(a) b = uf.find(b) ta = type(a) tb = type(b) # sa, sb = hm.show(a, b) # print('typeclass unify', a.show(), 'with:', b.show() ) assert ta is Var or tb is Var if ta is Var and tb is Var: # create a fresh constrained variable with constraint union depth = min(a.depth, b.depth) c = Var(depth, a.context | b.context ) # and link both uf.link(a, c) uf.link(b, c) return var = a if ta is Var else b other = a if tb is Var else b if type(other) is hm.Var: # constrained variable becomes representant uf.link(other, var) return # check instances for tc in var.context: # find a type scheme that matches 'other' in the # instances for this type constructor scheme, instance = tc.find_instance( other.nice(uf) ) # context reduction happens here: we instantiate the # type scheme (possibly containing bounded variables) # and unify with other # propagate further constraints, if any if any( type(b) is Var for b in scheme.bound ): # TODO what about the depth when instantiating scheme ? hm.unify(uf, hm.instantiate(scheme), other) # we made it so far, we may link now uf.link(var, other) return
def find_overload(self, identifier, mono): tool.debug('finding overload for:', identifier, ':', mono.show()) proto = self.definition[identifier] uf = tool.UnionFind() fresh = hm.instantiate(hm.generalize(proto)) vars = fresh.variables() assert len(vars) == 1 hm.unify(uf, fresh, mono) a = next(iter(vars)) t = uf.find( a ) scheme, instance = self.find_instance(t) return instance[identifier]