是否存在类型可以将字段内容考虑在内的语言?

时间:2011-06-04 02:20:30

标签: programming-languages types type-systems

我有这个疯狂的想法,并想知道是否存在这样的事情:

通常,在强类型语言中,类型主要涉及内存布局或抽象“类”的成员资格。因此class Foo {int a;}class Bar {int a; int b;}是截然不同的,但class Baz {int a; int b;}也是如此(尽管它具有相同的布局,但它是不同的类型)。到目前为止,非常好。

我想知道是否有一种语言允许人们指定更精细的约束关于什么是类型。例如,我想:

class Person {
    //...
    int height;
}

class RollercoasterSafe: Person (where .height>140) {}

void ride(RollercoasterSafe p) { //... }

并且编译器会确保p.height < 140中不可能有ride。这只是一个愚蠢的例子,但我确信有一些用例可以提供帮助。有这样的事吗?

4 个答案:

答案 0 :(得分:2)

这取决于是静态还是动态检查谓词。在任何一种情况下,答案都是肯定的,但结果系统看起来不同。

在静态端:PL研究人员提出了细化类型的概念,它由基类型和谓词组成:http://en.wikipedia.org/wiki/Program_refinement。我相信细化类型的想法是在编译时检查谓词,这意味着你必须将谓词的语言限制为易于理解的东西。

还可以使用依赖类型来表达约束,这些类型是由运行时值参数化的类型(与多态类型相反,它们由其他类型参数化)。

你可以使用强大的类型系统(如Haskell)进行其他技巧,但是你必须将heightint更改为类型检查器可以解释的结构。

在动态端:SQL有一个名为 domains 的东西,如CREATE DOMAINhttp://developer.postgresql.org/pgdocs/postgres/sql-createdomain.html(参见页面底部的一个简单示例)基本类型和约束。只要创建该域的值,就会动态检查域的约束 。通常,您可以通过创建新的抽象数据类型并在创建抽象类型的新值时执行检查来解决问题。如果您的语言允许您从新类型定义自动强制,那么您可以使用它们来实质上实现类似SQL的域;如果没有,你只需要使用简单的旧抽象数据类型。

然后有契约,它们本身并不被认为是类型,但可以以某些相同的方式使用,例如约束函数/方法的参数和结果。简单契约包括谓词(例如,“接受高度大于&gt; 140的Person对象”),但契约也可以是高阶的(例如,“接受其makeSmallTalk()方法永远不会返回null的Person对象”)。无法立即检查高阶合约,因此它们通常涉及创建某种代理。合同检查不会创建新类型的值或标记现有值,因此每次执行合同时都会重复进行动态检查。因此,程序员经常将合同放在模块边界上,以最大限度地减少冗余检查。

答案 1 :(得分:1)

具有此类功能的语言示例为Spec#。从项目网站上提供的教程文档:

  

考虑图1中的方法ISqrt,它计算整数平方根   给定的整数x。仅当x为非负数时才可以实现该方法,所以

int ISqrt(int x) 
  requires 0 <= x; 
  ensures result*result <= x && x < (result+1)*(result+1); 
{ 
  int r = 0; 
  while ((r+1)*(r+1) <= x) 
    invariant r*r <= x; 
  { 
    r++; 
  } 
  return r; 
} 

在你的情况下,你可能会做类似的事情(注意我没有试过这个,我只是在阅读文档):

void ride(Person p)
  requires p.height > 140;
{
  //...
}

可能有办法将requires子句汇总到您建议的RollercoasterSafe类型声明中。

答案 2 :(得分:0)

你的想法听起来有点像C ++ 0x的概念,虽然不完全相同。但是,已从C ++ 0x标准中删除了概念。

答案 3 :(得分:-1)

我不知道任何支持这种事情的语言,但我认为没有必要。

我非常确信只需在属性的设置器中应用验证就可以为您提供所有必要的限制。

在你的RollercoasterSafe类示例中,当height属性的值设置为小于140的值时,可能会抛出异常。这是运行时检查,但是多态可以使编译时检查不可能。