高级类型

方法

为达到自由度和表现力的最高级别,Luna允许以多态参数调用方法。

当然,并非总是可能推断结果的类型,所以,这种情况下,将此悬而未决到需要真正类型时。

如果熟悉动态语言的“鸭子类型(Duck Typing)”技术,在Luna中几乎是一样的,除了不是真的可能调用函数(except when it’s not really possible to call the functioni),用户仍然获得一个编译时错误。

考虑如下函数:

  1. def callSucc a: a.succ

是什么类型?

由于没有定义a的类型,分配一个类型参数b。

现在,类型b的succ方法是什么类型?

永远不知道,因为依赖所用a的具体类的实现。

因此,callSucc的类型简单的讲是“b->b.succ”。

可以这样读:需要一个类型是b的参数、返回类b的succ方法返回的任意值。

  1. callSucc 1
  2. succ方法为Int类型定义
  3. callSucc "hello"
  4. 会导致编译错误

类型假定(推断)和类型检查过程

Luna的类型检查器保存一些额外有关类型参数的假定,需要变量的类型代理(subsitute)满足。

这些经常出现在手写的函数和多态值上调用方法。

看一个简单例子,加法在Luna标准库中定义如下:

  1. def + :: a -> a -> a
  2. def + x y = x.+y

该定义允许写这样的表达式:

  1. 5 + 7
  2. "foo" + "bar"

却排斥:

  1. "foo" + 5 # 参数类型不同
  2. Just 5 + Just 7 # 没有给Maybe类定义加法

这里真正想表达什么(what is really going on here)?

用户指定的类型表明所有参数和返回值的类型必须相同,加法的使用表明类型a需要定义了加法,且需要一个类型是a的参数、返回值类型也是a。

这些要求可以描述为:

  1. + :: a -> a -> a

任何这样的a都有“a.+ = a -> a”。

这些都由Luna编译器在后台控制,用户不需要考虑所有假定呈现。

再考虑另一个例子:

  1. def foo x: x.succ + 1

该函数的类型是什么?

可以看到x.succ的结果和Int(1)相加,根据上述加法的定义,得知“x.succ :: Int”且该函数的返回值也是Int。

因此,最后潜在的类型推测是:

  1. foo :: a -> Int

任何这样的a都有“a.succ = Int”。

所有这些假定随着函数复杂、多行生长。

这是Luna咋后台追终的原因,仅在其中有些不满意时暴露。