def read_lang_functs():
    global __functs__
    __functs__ = dict(BASE_FUNCTS)
    f = open("corpora/geo-lambda.lang")

    typs = defaultdict(list)
    for line in f.readlines()[1:-2]:
        parts = re.split(r"[\(\)\s]", line)
        name = parts[1]
        typ = parts[2:-2]
        # marginally faster than w/o intermediate list
        btyp = tuple([base_typ(t) for t in typ])
        typs[name].append(btyp)
        # __functs__[name] = Typ.create(btyp)
    f.close()

    for name in typs:
        __functs__[name] = Typ.create_ambiguous(typs[name])
F_OR = "or"
F_NOT = "not"
F_EXISTS = "exists"

T_TRUTH = "t"
T_INT = "i"
T_ENTITY = "e"

BASE_FUNCTS = {
    F_ARGMAX: Typ.create((T_ENTITY, T_TRUTH, T_INT, T_ENTITY)),
    F_ARGMIN: Typ.create((T_ENTITY, T_TRUTH, T_INT, T_ENTITY)),
    F_COUNT: Typ.create((T_ENTITY, T_TRUTH, T_INT)),
    F_SUM: Typ.create((T_ENTITY, T_TRUTH, T_INT, T_INT)),
    F_LT: Typ.create((T_INT, T_INT, T_TRUTH)),
    F_GT: Typ.create((T_INT, T_INT, T_TRUTH)),
    F_AND: Typ.create_ambiguous([(T_TRUTH, T_TRUTH, T_TRUTH), (T_TRUTH, T_TRUTH, T_TRUTH, T_TRUTH)]),
    F_OR: Typ.create_ambiguous([(T_TRUTH, T_TRUTH, T_TRUTH), (T_TRUTH, T_TRUTH, T_TRUTH, T_TRUTH)]),
    F_NOT: Typ.create((T_TRUTH, T_TRUTH, T_TRUTH)),
    # TODO this actually a macro, not a function
    F_EXISTS: Typ.create((T_ENTITY, T_TRUTH, T_TRUTH)),
}

BASE_TYPES = [T_TRUTH, T_INT, T_ENTITY]

QUANTIFIERS = [F_ARGMIN, F_ARGMAX, F_COUNT, F_SUM, F_EXISTS]

__types__ = None
__functs__ = None

# TODO actually read
def read_lang_types():