静态types的完整Lisp变体是可能的吗?

静态types的完整Lisp变体是可能的吗? 这样的事情是否有意义存在? 我相信Lisp语言的优点之一就是其定义的简单性。 静态键入会破坏这个核心原则吗?

是的,这很可能,尽pipe标准的HM风格types系统通常是大多数习惯Lisp / Scheme代码的错误select。 请参阅“ Typed Racket” ,以了解最近使用静态types的“Full Lisp”语言(实际上更像Scheme)。

如果你只想要一个类似于 Lisp的静态types语言,那么你可以很容易地做到这一点,方法是定义一个代表你的语言的抽象语法树,然后将该AST映射到Sexpression式。 但是,我不认为我会调用Lisp的结果。

如果你希望除了语法之外还有一些实际上具有Lisp-y特性的东西,可以用静态types语言来完成。 但是,Lisp有很多特性,很难得到很多有用的静态输出。 为了说明,让我们看一下名为cons的列表结构本身,它构成了Lisp的主要构build块。

虽然(1 2 3)看起来像一个清单,但是把这个清单叫做清单是有点用词不当的。 例如,它与静态types列表完全不同,比如C ++的std::list或者Haskell的列表。 这些是单维链接列表,其中所有的单元格都是相同的types。 Lisp高兴地允许(1 "abc" #\d 'foo) 。 另外,即使将静态types列表扩展到列表列表,这些对象的types也要求列表中的每个元素都是一个子列表。 你如何表示((1 2) 3 4)

Lisp conses形成一个二叉树,叶子(primefaces)和分支(conses)。 此外,这样一棵树的叶子可能包含任何primefaces(非cons)Lisptypes! 这种结构的灵活性使得Lisp能够很好地处理符号计算,AST和转换Lisp代码本身!

那么如何用静态types语言来build模这样一个结构呢? 让我们在Haskell中尝试一下,它有一个非常强大和精确的静态types系统:

 type Symbol = String data Atom = ASymbol Symbol | AInt Int | AString String | Nil data Cons = CCons Cons Cons | CAtom Atom 

你的第一个问题将是Atomtypes的范围。 显然,我们并没有select一种足够灵活的Atomtypes来覆盖我们想要在conses中晃动的所有types的对象。 与其试图扩展上面列出的Atom数据结构(您可以清楚地看到它是脆弱的),假设我们有一个神奇的typesAtomic ,它区分了所有我们想要创build的types。 那么我们可以试试:

 class Atomic a where ????? data Atomic a => Cons a = CCons Cons Cons | CAtom a 

但是这不起作用,因为它要求树中的所有primefaces都是相同types的。 我们希望他们能够从叶到叶不同。 一个更好的方法需要使用Haskell的存在量词

 class Atomic a where ????? data Cons = CCons Cons Cons | forall a. Atomic a => CAtom a 

但是现在你来到这个问题的症结所在。 你能用这种结构的primefaces做什么? 他们有什么共同的结构,可以模仿Atomic a ? 你保证这种types的安全级别是什么? 请注意,我们没有在我们的types类中添加任何函数,并且有一个很好的原因:在Lisp中,这些primefaces没有什么共同之处。 它们在Lisp中的超types简单地称为t (即top)。

为了使用它们,你必须想出一些机制来dynamic地将primefaces的值强制转换为你实际可以使用的值。 在那个时候,你基本上已经在你的静态types语言中实现了一个dynamictypes的子系统! (人们不禁要提到格林斯潘的第十编程规则的一个必然结论。)

请注意,Haskell为Objtypes的dynamic子系统提供了支持,与Dynamictypes和types类一起使用来替代我们的Atomic类,它允许任意值与它们的types一起存储,并从那些types中显式强制types。 这就是你需要用Lisp cons结构进行全面通用的一种系统。

你也可以做另一种方式,在一个基本上dynamictypes的语言中embedded一个静态types的子系统。 这使您可以利用静态types检查来检查程序中可以利用更严格types要求的部分。 例如,这似乎是CMUCL有限forms的精确types检查的方法 。

最后,可能有两个独立的子系统,dynamic和静态types,使用契约式编程来帮助导航两者之间的转换。 这样,语言可以适应Lisp的用法,静态types检查比帮助更容易受到阻碍,而且静态types检查也是有利的。 这是Typed Racket所采用的方法,您将从下面的评论中看到。

我的回答可能是没有高度自信的。 例如,如果您查看SML这样的语言,并将其与Lisp进行比较,则每个语言的function核心几乎完全相同。 因此,对Lisp的核心(函数应用程序和原始值)应用某种静态types似乎不会有太大麻烦。

你的问题确实说得很清楚,而且我发现有些问题是代码 – 数据方法。 types存在于比expression式更抽象的层次上。 Lisp没有这个区别 – 在结构上一切都是“平坦的”。 如果我们考虑一些expression式E:T(其中T是它的types的一些表示),那么我们认为这个expression式是普通的数据,那么T的types究竟是什么? 那么,这是一种! 一种是更高阶的types,所以让我们继续在我们的代码中说一些:

 E : T :: K 

你可能会看到我要去哪里。 我敢肯定,通过从代码中分离出types信息,就有可能避免这种types的自我指涉,然而这会使得types不是很“口齿不清”。 可能有很多方法可以解决这个问题,尽pipe对我来说这不是最好的。

编辑:哦,所以用一点googlesearch,我发现齐 ,除了它是静态types,似乎是非常类似于Lisp。 也许这是一个很好的地方,看看他们做了哪些修改,从而获得静态的input。

Dylan: http : //visualization.dylan-user.org/diploma.pdf