'Infer and check types.  Raise exceptions if necessary.
:param signature: dict that maps variable names to types (or string
representations of types)
:return: the signature, plus any additional type mappings'

def typecheck(self, signature=None):

    sig = defaultdict(list)
    if signature:
        for key in signature:
            val = signature[key]
            varEx = VariableExpression(Variable(key))
            if isinstance(val, Type):
                varEx.type = val
            else:
                varEx.type = read_type(val)
            sig[key].append(varEx)
    self._set_type(signature=sig)
    return dict(((key, sig[key][0].type) for key in sig))
