【发布时间】:2020-09-23 21:33:40
【问题描述】:
在下面的 Typescript 代码中,我有两个结构相似的类型:Nat,它是 Zero 或 Succ<Nat>,和 Letter,它是 A 或 Succ<Letter> ,其中Succ 是一个简单的容器类型。
type Zero = 0;
type A = 'A';
class Succ<T> {
constructor(public pred: T){}
}
type Nat= Zero | Succ<Nat>
type Letter = A | Succ<Letter>
function next(x: ?): ?{
return new Succ(x);
}
我的问题是,我如何键入next 函数,它基本上只是包装在函数调用中的Succ 的构造函数?本质上是为了声明,如果你传入Nat,你会得到一个Nat,如果你传入一个Letter,你会得到一个Letter。
我试过了:
type Countable = Nat | Letter
function next<T extends Countable>(x: T): T { ...
我收到了Type 'Succ<T>' is not assignable to type 'T'. 'T' could be instantiated with an arbitrary type which could be unrelated to 'Succ<T>'.
我也试过直接重载:
function next(x: Nat): Nat;
function next(x: Letter): Letter {
return new Succ(x);
}
但这会返回签名与实现不兼容的错误。
我尝试直接投射它:
function next<T extends Countable>(x: T): T {
return new Succ(x) as T;
}
这会返回一个错误,Conversion of type 'Succ<T>' to type 'T' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. 'T' could be instantiated with an arbitrary type which could be unrelated to 'Succ<T>'.
所以我做了:return new Succ(x) as unknown as T;
这工作,但感觉很脏(感觉就像投到 void 并返回)。作为健全性检查,const x: Letter = next(0); 正确地抛出了 Type '0' is not assignable to type 'Letter'. 的类型错误
这里发生了什么?我在写轨道上吗?有没有更优雅的解决方案?
上下文:
我正在开发一个 lambda 演算解释器,来自 函数式编程语言的实现。有几个不同的 AST——核心 lambda 演算、核心 lambda 演算 + let 表达式、核心 lambda 演算 + let + 模式匹配等。目前我设置它的方式是每个构造是一个类,递归的将AST的类型作为参数,所以我们有Variable、Abstraction<AST>、Application<AST>、Let<AST>等,然后每种不同类型的AST都表示为一个联合,所以
type OrdinaryLambdaCalculus =
| Variable
| Abstraction<OrdinaryLambdaCalculus>
| Application<OrdinaryLambdaCalculus>;
type AugmentedLambdaCalculus =
| Variable
| Abstraction<AugmentedLambdaCalculus>
| Application<AugmentedLambdaCalculus>
| Let<AugmentedLambdaCalculus>
到目前为止它运行良好,但我希望能够编写一个函数,该函数采用一个或多个 AST 表达式,并通过添加结构构造一个相同类型的新 AST,例如:
function etaAbstraction<T extends AST>(ast: T): T {
let newVar = findFree(ast);
return new Abstraction(newVar, new Application(ast, newVar));
}
这就是我在获取正确类型时遇到的麻烦。
【问题讨论】:
标签: typescript recursion functional-programming algebraic-data-types