Types 在Ocaml中定义lambda表达式的类型

Types 在Ocaml中定义lambda表达式的类型,types,ocaml,Types,Ocaml,实际上,我试图定义一个对应于lambda演算表达式的类型,该表达式由变量、抽象和应用程序组成。我目前最好的尝试是: type expr = Var of string | Abs of expr * expr | App of expr * expr 但是,我想将Abs的第一部分限制为Var。例如,我希望这是一个格式错误的表达式: Abs(Abs(Var "foo", Var "bar"), Var "bar") 但它目前被认为是有效的。我还想要求应用程序的第一部分必须是Abs。有没有办法让

实际上,我试图定义一个对应于lambda演算表达式的类型,该表达式由变量、抽象和应用程序组成。我目前最好的尝试是:

type expr = Var of string | Abs of expr * expr | App of expr * expr
但是,我想将
Abs
的第一部分限制为
Var
。例如,我希望这是一个格式错误的表达式:

Abs(Abs(Var "foo", Var "bar"), Var "bar")
但它目前被认为是有效的。我还想要求
应用程序的第一部分必须是
Abs
。有没有办法让类型系统强制执行这些限制,或者这会使它超出设计的目的


编辑:如果不清楚,
Abs(Var“x”,Var“x”)
应该被认为是有效的。

问题是您已经定义了
Abs
来接受两个
expr
,每个可能是
Var
Abs
App

Abs牵引力应包括一个变量和表达式,而不是两个表达式。在这种情况下,变量只是一个字符串,因此
Abs
应该由字符串和表达式组成

将其更改为:

Abs of string * expr

您无法让类型系统直接强制执行类似的内容。相反,我会考虑定义两种类型:

type variable = Name of string
type expr = Var of variable | Abs of variable * expr | App of expr * expr

这与Jeff的答案类似,但是您可以自由地更改用于定义变量的类型,而不必担心在两个地方进行更改。这两种方法都是处理问题的有效方法。

AFAIU,您需要gadt来实现这一点,它最近被合并到svn trunk中

以下是业余爱好者的示例(可能不完全正确,但它满足您的要求):

让您定义数据类型的子类型。子类型强制执行简单的结构约束

例如,这里是具有多态变体的lambda术语的定义,以及头部范式的子类型的定义

type var = [ `Var of string ]

type expr = [
  | var
  | `Abs of var * expr
  | `App of expr * expr
  ]

type irr (*non-head-reducible applications*) = [
  | var
  | `App of irr * expr
  ]
type hnf (*head normal forms*) = [
  | irr
  | `Abs of var * hnf
  ]

let substitution (x : var) (u : expr) : expr -> expr =
  failwith "left as an exercise"

(*Iterated head reductions produce a head normal form*)
let rec head_reductions : expr -> hnf = function
  | #var as x -> x
  | `Abs (x, u) -> `Abs (x, head_reductions u)
  | `App (u, v) ->
      match head_reduction u with
      | #irr as u -> u
      | `Abs (x, w) -> head_reductions (substitution x u (w :> expr))

谢谢你的回答。这是有帮助的,但我应该更具体一些:我希望
Abs(Var(“x”),Var(“x”)
是有效的,但是,你的答案中有代码,这是不确定的,但是Abs(Name(“x”),Var(Name(“x”))是有效的。这只是结构上的一个微小变化,似乎接受了我想要它拒绝的例子:
`Abs(`Abs(`Var“foo”,“Var”bar”),`Var“bar”)
。我遗漏了什么?@JoshJordan多态变体类型不是生成的(这就是为什么你可以用它们进行子类型化)。您拥有的是一个有效的Caml表达式。但它不是
expr
类型。谢谢。在我的问题中,我可能措辞不好,但我希望能够定义类型
expr
,这样上面的表达式就是那种类型的。@JoshJordan所以……你刚才告诉我你不希望表达式是
expr类型,你希望表达式是
expr`类型。其中一项要求必须给出。多态变体绝对是实现简单结构子类型的好方法。我不明白你在这里想干什么。旁注:出于许多目的,使用de Bruijn索引定义lambda术语是有意义的——这避免了在执行替换时重命名变量的麻烦。
type var = [ `Var of string ]

type expr = [
  | var
  | `Abs of var * expr
  | `App of expr * expr
  ]

type irr (*non-head-reducible applications*) = [
  | var
  | `App of irr * expr
  ]
type hnf (*head normal forms*) = [
  | irr
  | `Abs of var * hnf
  ]

let substitution (x : var) (u : expr) : expr -> expr =
  failwith "left as an exercise"

(*Iterated head reductions produce a head normal form*)
let rec head_reductions : expr -> hnf = function
  | #var as x -> x
  | `Abs (x, u) -> `Abs (x, head_reductions u)
  | `App (u, v) ->
      match head_reduction u with
      | #irr as u -> u
      | `Abs (x, w) -> head_reductions (substitution x u (w :> expr))