Coall如何实施

时间:2019-03-01 06:52:54

标签: coq

在尝试了解如何在JS或Ruby中implement forall的过程中,我很想知道它在Coq中是如何实现的。也许这将有助于阐明。我似乎无法通过在Google上搜索来找到定义。主要只是在某处的源代码中查找链接。

1 个答案:

答案 0 :(得分:3)

Coq的foralldependent product type,不能直接用动态类型语言(如Javascript)进行编码,因为它们只是缺少静态类型的概念。

从某些语言,功能的角度来看,它的目的是为某些荒谬的事物提供静态类型。假设我们有类型T1T2 ...

的无限集合

然后不能通过常规方法将此函数分配为(非平凡的)类型:

function foo(n) {
  return eval("new T" + n + "()");
}

但是,我们可以使用辅助函数为它提供依赖(forall)类型

function H(n) {
  return eval("T" + n);
}

然后foo的类型将为forall n:Number, H(n)(给定Number,返回类型为H(n)的对象,即Tn)。

不幸的是,我们无法将这些信息传达给JS解释器以静态执行此合同。但是,我们可以在运行时检查它!

让我们从建立一个小的类型检查框架开始。

function type_number(x) {
  if (typeof x == "number") return x;
  throw new Error("not a number");
}

function type_function(x) {
  if (typeof x == "function") return x;
  throw new Error("not a function");
}

function type_instance(clss) {
  return function (x) {
    if (x instanceof clss) return x;
    throw new Error("not an instance of " + clss);
  };
}

现在我们可以实现非依赖函数类型

function type_arrow(arg, ret) {
    return function(f) {
        f = type_function(f);
        return function(x) {
            return ret(f(arg(x)));
        };
    };
}

此处arg必须是参数的类型检查器,而ret必须是返回值的类型检查器。例如:

// declare a function from numbers to numbers
var fn1 = type_arrow(type_number, type_number)((x) => x * x);
fn1(10); // works
fn1("asdsa"); // fails

// bad declaration, but, unfortunately, JS cannot possibly catch it at "compilation" time
var fn2 = type_arrow(type_number, type_number)((x) => "Hello!");
fn2(10); // fails, return value is not a number

现在有趣的部分:

function type_forall(arg, ret) {
    return function(f) {
        f = type_function(f);
        return function(x) {
            var y = f(arg(x));
            return ret(x)(y);
        };
    };
}

请注意,ret现在是两个参数的咖喱函数。在我的第一个示例中,我们现在可以为foo指定类型:

function T1(){}
function T2(){}
function T3(){}
function T4(){}
function T5(){}
// ...etc

function foo(n) {
    return eval("new T" + n + "()");
}

function H(n) {
    return eval("T" + n);
}

function type_H(n) {
    return type_instance(H(n));
}

var typed_foo = type_forall(type_number, type_H)(foo);
typed_foo(2); // successfully invokes and returns a T2 instance

请注意,我们不能用footype_arrow赋予非平凡类型-我们需要n来正确地对返回值进行类型检查。

但这远不及Coq给我们的力量,仅仅是因为它在编译时不会捕获任何错误。如果您确实需要这些保证,则必须将语言构造具体化为一流对象并执行自己的类型检查。我可以推荐的一篇文章是http://augustss.blogspot.com/2007/10/simpler-easier-in-recent-paper-simply.html