或数据类型的模式。部分作为?

or-pattern on datatype. Partial as?

试图将 lambda 演算解释器拼凑成一个菜鸟项目,但我遇到了一个我不太明白的语法问题。

问题是一个类型的两个构造函数在某些方面表现相同,我想避免代码重复。请参阅下面的代码。

type term =
  | Lam of string * term * term
  | Pi of string * term * term

let rec subst x t s = match s with
  | Lam (y,r,q) | Pi (y,r,q) ->
    if x = y then LAMORPI (y, subst x t r, q)
    else [...]

我认为所谓的 or-patterns 似乎很合适,但我无法让它工作。我想也许这就是目的,但我似乎不能部分地作为某种东西,这就是我对 LAMORPI 的想法。这种情况似乎有一个简洁或常用的惯用解决方案,但我的 google-fu 不够强大。

通常或可能的解决方案是什么?

不能在表达式中使用 or-pattern。 (这个潜在的特性引发了一些问题:请参阅 http://gallium.inria.fr/blog/pattern-synonyms-as-expressions 进行讨论)

一种可能性是重构您的类型以暴露两个构造函数仅在标记上不同的事实:

type kind = Lam | Pi
type term =
  | LamPi of tag * string * term * term
  | ...

let rec subst x t s = match s with
  | LamPi (tag,y,r,q) ->
    if x = y then LamPi (tag, y, subst x t r, q)
    else ...