模式与构造函数的参数数量匹配

时间:2019-07-23 18:27:44

标签: pattern-matching ocaml variant

我想创建一个函数inc,其功能如下:

type operation = MulNeg | Add n | Sub n
let ops = [Add 3; Add 4; Sub 2; MulNeg] in
let inc l = ... in
inc ops (* should return [Add 4; Add 5; Sub 3; MulNeg] *)

我知道我可以这样实现:

let inc l = List.map (function 
    | MulNeg -> MulNeg
    | Add a -> Add (a + 1)
    | Sub a -> Sub (a + 1)
  ) l

但是,在我的程序中,还有更多的操作,因此,我的目标是拥有一个根据构造函数的参数数量起作用的函数。我最接近的是:

let inc l = List.map (function
    | op a -> op (a + 1)
    | op -> op
  ) l

但是,这会在op a上引发错误。有没有合法的方法可以建立这种模式?

1 个答案:

答案 0 :(得分:3)

您无法对构造函数参数的数量进行模式匹配。 但是,解决您的问题的常见方法是引入额外的间接方式,例如

type binop = Add | Sub | Mul | Div
type unop = Inc | Dec | Ref
type exp = 
  | Const of int
  | Var of string
  | Unop of unop * exp
  | Binop of binop * exp * exp

let rec incr = function
  | Const x -> Const (x+1)
  | Var _ as v -> v
  | Binop (op,x,y) -> Binop (op,incr x, incr y)
  | Unop (op,x) -> Unop (op, incr x)

当然,当您具有带有任意数量参数的构造函数时,这不会扩展。然后,您需要更改表示形式或坚持其他某种抽象。例如,可以将Lisp样式的语言编码如下,

type prim = Add | Sub | Mul | Div
type op = Fun of string | Prim of prim
type exp = 
  | App of op * exp list
  | Atom of string

如果两种解决方案都不适合您,则您不应使用代数数据类型,而应遵循访客模式。