针对构造函数的参数数量的模式匹配
Pattern matching against the number of arguments of a constructor
我想创建一个函数 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
上引发错误。有合法的方法来制作这样的图案吗?
您不能对构造函数参数的数量进行模式匹配。
但是,您的问题的一个常见解决方案是引入一个额外的间接寻址,例如,
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-style 语言可以编码如下,
type prim = Add | Sub | Mul | Div
type op = Fun of string | Prim of prim
type exp =
| App of op * exp list
| Atom of string
如果这两种解决方案都不适合您,那么您不应该使用代数数据类型,而是坚持访问者模式。
我想创建一个函数 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
上引发错误。有合法的方法来制作这样的图案吗?
您不能对构造函数参数的数量进行模式匹配。 但是,您的问题的一个常见解决方案是引入一个额外的间接寻址,例如,
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-style 语言可以编码如下,
type prim = Add | Sub | Mul | Div
type op = Fun of string | Prim of prim
type exp =
| App of op * exp list
| Atom of string
如果这两种解决方案都不适合您,那么您不应该使用代数数据类型,而是坚持访问者模式。