在类型推断需要“统一”的最简单的例子(Simplest example of need for “u

2019-07-30 06:24发布

我试图让我周围的类型推断是如何实现的头。 在特别的,我不太看到/为什么“统一”的繁重进场。

我给的“伪C#”,以帮助澄清一个例子:

用简单的方式做这将是这样的:

假设你用“解析”你的程序到一个表达式树,使得它可以与执行:

interface IEnvironment
{
    object lookup(string name);
}

interface IExpression
{
    // Evaluate this program in this environment
    object Evaluate(IEnvironment e);
}

因此,像“乘法”可能会实现:

class Multiply : IExpression
{
    IExpression lhs;
    IExpression rhs;
    // etc.
    public object Evaluate(IEnvironment e)
    {
        // assume for the moment C# has polymorphic multiplication
        return lhs.Evaluate(e) * rhs.Evaluate(e);
    }
}

然后以“落实”式的推理,你可能只是这样做:

interface ITypeEnvironment
{
    Type getType(string name);
}

interface IExpression
{
    //as before
    object Evaluate(IEnvironment e);
    // infer type
    Type inferType(ITypeEnvironment typeEnvironment);
}

然后,“乘法”的类型推断可能仅仅是这样的:

class Multiply : IExpression
{
    IExpression lhs;
    IExpression rhs;

    // ... 
    public Type inferType(ITypeEnvironment typeEnvironment)
    {
        Type lhsType = lhs.inferType(typeEnvironment);
        Type rhsType = rhs.inferType(typeEnvironment);
        if(lhsType != rhsType)
             throw new Exception("lhs and rhs types do not match");

        // you could also check here that lhs/rhs are one of double/int/float etc.
        return lhsType;
    }
}

LHS和RHS可能很简单的常量,或者在环境中抬头“变量”:

class Constant : IExpression
{
    object value;
    public Type inferType(ITypeEnvironment typeEnvironment)
    {
        return value.GetType(); // The type of the value;
    }
    public object Evaluate(IEnvironment environment)
    {
        return value;
    }
}

class Variable : IExpression
{
    string name;
    public Type inferType(ITypeEnvironment typeEnvironment)
    {
        return typeEnvironment.getType(name);
    }
    public object Evaluate(IEnvironment environment)
    {
        return environment.lookup(name);
    }
}

但无处在做这我们最终需要一个“统一”的算法。

因此,很明显,我的例子是不是足够复杂。 是否需要更高阶的功能呢? 我们需要“参数多态性”?

什么是最简单的可能的例子,其中“统一”实际需要正确地推断表达式的类型。

在方案的一个例子是理想的(即,在那里你需要统一正确推断s表达式的类型的非常小的方案程序的例子)。

Answer 1:

 public Type inferType(ITypeEnvironment typeEnvironment) { return typeEnvironment.getType(name); } 

如果你只是不知道该变量的类型? 这是类型推断的整点,对不对? 像这样的事情很简单(在一些伪语言):

function foo(x) { return x + 5; }

你不知道的类型x ,直到你推断此外,并认识到它必须是一个整数,因为它加上一个整数,或者类似的东西。

如果你有什么另一个这样的功能:

function bar(x) { return foo(x); }

你想不通的类型x ,直到你已经想通了的类型foo ,等等。

所以,当你第一次看到一个变量,你必须只分配了一个变量一些占位类型,再后来,当变量传递给某种功能或某事,你要“统一”,它与参数类型的功能。



Answer 2:

让我完全忽略你的榜样,给你的,我们做的方法类型推断在C#中的例子。 (如果这个话题感兴趣的内容,那么我建议你阅读“ 类型推断 ”我的博客的档案。)

考虑:

void M<T>(IDictionary<string, List<T>> x) {}

在这里,我们有一个通用的方法M.这需要映射到字符串T的名单字典假设你有一个变量:

var d = new Dictionary<string, List<int>>() { ...initializers here... };
M(d);

我们称M<T>而不提供类型参数,所以编译器必须推断出它。

编译器通过“统一”这样做Dictionary<string, List<int>>IDictionary<string, List<T>>

首先,它确定Dictionary<K, V>实现IDictionary<K, V>

从我们推断, Dictionary<string, List<int>>实现IDictionary<string, List<int>>

现在,我们对比赛IDictionary一部分。 我们统一串线,这显然是所有好的,但我们从中学到什么。

然后我们统一清单,清单,并认识到,我们不得不再次递归。

然后我们统一用INT T,并且认识到int是对T的束缚

类型推理算法的一班班距离,直到它可以使没有更多的进展,然后它开始从它的推论做进一步的推论。 对T的唯一绑定类型为int,所以我们推断,调用者必须想吨至是int。 所以我们称之为M<int>

明白了吗?



Answer 3:

假设我们有一个函数

F(X,Y)

其中X可能是如FunctionOfTwoFunctionsOfInteger,也可能是FunctionOfInteger。

假设我们在传递

F(克(U,2),G(1,Z))

现在统一,u被绑定到1,和z势必2,所以第一个参数是一个FunctionOfTwoFunctionsOfInteger。

所以,我们必须推断x和y的类型都是FunctionOfTwoFunctionsOfInteger

我不是太熟悉C#,但与lambda表达式(或等同的代表或其他)这也许应该是可能的。

对于其中的类型推断是提高定理证明的速度是非常有用的一个例子,看看“舒伯特的压路机”

http://www.rpi.edu/~brings/PAI/schub.steam/node1.html

有专门的解决方案和配方对这个问题的杂志自动推理的问题,其中大部分是在定理证明系统涉及类型的推理:

http://www.springerlink.com/content/k1425x112w6671g0/



文章来源: Simplest example of need for “unification” in type inference