typed/racket 的有界参数化类型

Bounded parameterized types with typed/racket

假设我有一个函数对 base 类型的值和 returning base 类型的值进行操作:

(struct base ([x : Real]))
(struct child base ([y : String]))

(: fun (base base → base))
(define (fun a b)
  (if (> (base-x a) (base-x b))
      a
      b))

函数fun也可以限制为类型child,在这种情况下它保证return类型child的值(无需修改代码):

(: fun (child child → child))

也可以让它接受 basechild 值,和 return 相同的类型:

(: fun (case→ (base base → base)
              (child child → child)))

这缺少界限,并且由于显而易见的原因而失败:

(: fun (All (T) (T T → T)))

当有很多 child 类型时,如何通过提供 All 的绑定来简化它?

我正在寻找与此类似的语法:

(: fun (All (T : base) (T T → T)))

不直接支持,但在 latest snapshot versions, it's possible to simulate that with intersection types:

(: fun : (All (T) ((∩ base T) (∩ base T) → (∩ base T))))

然后 fun returns 当给定 basechild 类型的混合时,它可以得到最具体的类型:

> (fun (base 1) (base 2))
- : base
#<base>
> (fun (base 1) (child 2 "string"))
- : base
#<child>
> (fun (child 1 "string") (base 2))
- : base
#<base>
> (fun (child 1 "string") (child 2 "string"))
- : (∩ child base)
#<child>
> (ann (fun (child 1 "string") (child 2 "string")) child)
- : child
#<child>

并且您可以在需要 child 的上下文中使用 (∩ child base)