Tôi đang làm việc trên một trình biên dịch cho một ngôn ngữ nối và muốn thêm hỗ trợ suy luận kiểu. Tôi hiểu Hindley, Milner, nhưng tôi đã học lý thuyết loại khi tôi đi, vì vậy tôi không chắc làm thế nào để thích nghi với nó. Là hệ thống sau đây âm thanh và có thể suy luận chắc chắn?
Một thuật ngữ là một nghĩa đen, một thành phần của các thuật ngữ, một trích dẫn của một thuật ngữ hoặc nguyên thủy.
All terms denote functions. For two functions and , , that is, juxtaposition denotes reverse composition. Literals denote niladic functions.
The terms other than composition have basic type rules:
Notably absent are rules for application, since concatenative languages lack it.
A type is either a literal, a type variable, or a function from stacks to stacks, where a stack is defined as a right-nested tuple. All functions are implicitly polymorphic with respect to the “rest of the stack”.
This is the first thing that seems suspect, but I don’t know exactly what’s wrong with it.
To help readability and cut down on parentheses, I’ll assume that in type schemes. I’ll also use a capital letter for a variable denoting a stack, rather than a single value.
There are six primitives. The first five are pretty innocuous. dup
takes the topmost value and produces two copies of it. swap
changes the order of the top two values. pop
discards the top value. quote
takes a value and produces a quotation (function) that returns it. apply
applies a quotation to the stack.
The last combinator, compose
, ought to take two quotations and return the type of their concatenation, that is, . In the statically typed concatenative language Cat, the type of compose
is very straightforward.
However, this type is too restrictive: it requires that the production of the first function exactly match the consumption of the second. In reality, you have to assume distinct types, then unify them. But how would you write that type?
If you let denote a difference of two types, then I think you can write the type of compose
correctly.
This is still relatively straightforward: compose
takes a function and one . Its result consumes atop the consumption of not produced by , and produces atop the production of not consumed by . This gives the rule for ordinary composition.
However, I don’t know that this hypothetical actually corresponds to anything, and I’ve been chasing it around in circles for long enough that I think I took a wrong turn. Could it be a simple difference of tuples?
Is there something horribly broken about this that I’m not seeing, or am I on something like the right track? (I’ve probably quantified some of this stuff wrongly and would appreciate fixes in that area as well.)
compose
is too restrictive? I have the impression that this is fine like this. (e.g. the restriction could be handled by unification like for application in like in the λ-calculus)
twice
defined as dup compose apply
, which takes a quotation and applies it twice. [1 +] twice
is fine: you’re composing two functions of type . But [pop] twice
is not: if , the problem is that , so the expression is disallowed even though it ought to be valid and have type . The solution is of course to put the qualifier in the right place, but I’m mainly wondering how to actually write the type of compose
without some circular definition.