Beispiel #1
0
    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]
Beispiel #2
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
Beispiel #3
0
    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]