当前位置:  开发笔记 > 编程语言 > 正文

在类型推断中需要"统一"的最简单的例子

如何解决《在类型推断中需要"统一"的最简单的例子》经验,为你挑选了1个好方法。

我试图了解如何实现类型推断.特别是,我不太清楚"统一"的繁重发挥在何处/为何发挥作用.

我将举一个"伪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);
    }
}

但在这方面,我们最终还是需要一种"统一"算法.

所以,显然,我的例子不够复杂.它需要更高阶的功能吗?我们需要"参数多态"吗?

什么是最简单的可能示例,其中实际需要"统一"来正确推断表达式的类型.

Scheme中的一个例子是理想的(即一个非常小的Scheme程序的例子,你需要统一才能正确地推断出s-expression的类型).



1> Eric Lippert..:

让我完全忽略您的示例,并举例说明我们在C#中进行方法类型推断的位置.(如果您对此主题感兴趣,那么我建议您阅读我博客的" 类型推断 "存档.)

考虑:

void M(IDictionary> x) {}

这里我们有一个通用的方法M,它采用一个将字符串映射到T列表的字典.假设你有一个变量:

var d = new Dictionary>() { ...initializers here... };
M(d);

我们在M没有提供类型参数的情况下调用,因此编译器必须推断它.

编译器通过"统一" Dictionary>来实现IDictionary>.

首先它确定了Dictionary实现IDictionary.

从那以后我们推断出那个Dictionary>工具IDictionary>.

现在我们有一个匹配的IDictionary部分.我们用字符串统一字符串,这显然都很好但我们从中学不到任何东西.

然后我们将List与List统一,并意识到我们必须再次递归.

然后我们用T统一int,并意识到int是T的绑定.

类型推断算法逐渐消失,直到它不再有进展,然后它开始从推论中进一步推断.T上唯一的绑定是int,所以我们推断出调用者必须要T为int.所以我们打电话M.

明白了吗?

推荐阅读
爱唱歌的郭少文_
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有