我想创建一个函数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
上引发错误。有没有合法的方法可以建立这种模式?
答案 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
如果两种解决方案都不适合您,则您不应使用代数数据类型,而应遵循访客模式。