Functional programming 大类型上的模式匹配,一种减少代码大小的方法

Functional programming 大类型上的模式匹配,一种减少代码大小的方法,functional-programming,ocaml,Functional Programming,Ocaml,假设我有一个新的“大”类型。 例如,假设我有«公式»类型: type formule = |VRAI |Predicat of char |NON of formule |ET of formule * formule |OU of formule * formule |X of formule |G of formule |F of formule |U of formule * formule 现在我想要一个计算类型«formu

假设我有一个新的“大”类型。 例如,假设我有«公式»类型:

    type formule =
   |VRAI
   |Predicat of char
   |NON of formule
   |ET of formule * formule
   |OU of formule * formule
   |X of formule
   |G of formule
   |F of formule
   |U of formule * formule
现在我想要一个计算类型«formule»大小的函数。为此,我们可以使用计算二叉树节点数的相同算法。这里的问题是,如果我进行模式匹配,我必须处理很多情况,这很烦人

如果我能像下面的«taille»函数一样在参数数量上进行模式匹配,那就太好了:

  let rec taille = function
  |VRAI || Predicat(_) -> 1
  |_(a) -> 1 + taille a
  |_(a,b) -> 1 + taille a + taille b
问题是这不起作用。当我编译以下代码时:

type formule =
   |VRAI
   |Predicat of char
   |NON of formule
   |ET of formule * formule
   |OU of formule * formule
   |X of formule
   |G of formule
   |F of formule
   |U of formule * formule

let rec taille = function
  |VRAI || Predicat(_) -> 1
  |_(a) -> 1 + taille a
  |_(a,b) -> 1 + taille a + taille b
我得到以下错误:

File "main.ml", line 1, characters 192-195:
Error: Syntax error
我认为这是因为我的模式匹配不正确,但在这种情况下,为什么我在第一行有错误

此外,如果它确实来自我的模式匹配,是否有一种方法可以像«taille»一样进行模式匹配(在参数数量上进行模式匹配,以减少案例数量)


谢谢大家!

不能在这样的模式中使用二进制析取运算符。但是,有一个模式匹配快捷方式可以满足您的需要:

let rec taille = function
  | VRAI | Predicat _ -> 1
  | NON a | X a | G a | F a -> 1 + taille a
  | ET (a, b) | OU (a, b) | U (a, b) -> 1 + taille a + taille b
一个论点和两个论点的情况并不像你希望的那样简洁,但我认为不可能做得更好。您不能在构造函数上使用通配符(

另一个想法是在辅助函数中捕获“提取参数”模式:

let args = function
  | VRAI | Predicat _ -> []
  | NON a | X a | G a | F a -> [a]
  | ET (a, b) | OU (a, b) | U (a, b) -> [a; b]
然后你可以写:

let rec taille f = List.fold_left (fun a x -> a + taille x) 1 (args f)
或者,如果没有中间列表:

let fold_args f1 f2 c =
  let rec g = function
    | VRAI | Predicat _ -> c
    | NON a | X a | G a | F a -> f1 (g a)
    | ET (a, b) | OU (a, b) | U (a, b) -> f2 (g a) (g b)
  in
  g

let taille = fold_args (fun x -> 1 + x) (fun x y -> 1 + x + y) 1

不能在这样的模式中使用二进制析取运算符。但是,有一个模式匹配快捷方式可以满足您的需要:

let rec taille = function
  | VRAI | Predicat _ -> 1
  | NON a | X a | G a | F a -> 1 + taille a
  | ET (a, b) | OU (a, b) | U (a, b) -> 1 + taille a + taille b
一个论点和两个论点的情况并不像你希望的那样简洁,但我认为不可能做得更好。您不能在构造函数上使用通配符(

另一个想法是在辅助函数中捕获“提取参数”模式:

let args = function
  | VRAI | Predicat _ -> []
  | NON a | X a | G a | F a -> [a]
  | ET (a, b) | OU (a, b) | U (a, b) -> [a; b]
然后你可以写:

let rec taille f = List.fold_left (fun a x -> a + taille x) 1 (args f)
或者,如果没有中间列表:

let fold_args f1 f2 c =
  let rec g = function
    | VRAI | Predicat _ -> c
    | NON a | X a | G a | F a -> f1 (g a)
    | ET (a, b) | OU (a, b) | U (a, b) -> f2 (g a) (g b)
  in
  g

let taille = fold_args (fun x -> 1 + x) (fun x y -> 1 + x + y) 1

在您的情况下,我将重构类型
公式
,如下所示:

type infix = ET | OU | U

type prefix = NON | X | G | F

type formule =
  | VRAI
  | Predicat of char
  | Infix of formule * infix * formule
  | Prefix of prefix * formule
let rec taille = function
  | VRAI | Predicat _ -> 1
  | Prefix (_, a) -> 1 + taille a
  | Infix (a, _, b) -> 1 + taille a + taille b
我不知道您正在使用的域,但我想这是一种带有前缀和中缀运算符的语言

然后您可以这样编写
taille
函数:

type infix = ET | OU | U

type prefix = NON | X | G | F

type formule =
  | VRAI
  | Predicat of char
  | Infix of formule * infix * formule
  | Prefix of prefix * formule
let rec taille = function
  | VRAI | Predicat _ -> 1
  | Prefix (_, a) -> 1 + taille a
  | Infix (a, _, b) -> 1 + taille a + taille b

现在,您的类型更细粒度了,您可能会发现在新类型上有意义的新函数

在您的情况下,我将重构类型
公式
,如下所示:

type infix = ET | OU | U

type prefix = NON | X | G | F

type formule =
  | VRAI
  | Predicat of char
  | Infix of formule * infix * formule
  | Prefix of prefix * formule
let rec taille = function
  | VRAI | Predicat _ -> 1
  | Prefix (_, a) -> 1 + taille a
  | Infix (a, _, b) -> 1 + taille a + taille b
我不知道您正在使用的域,但我想这是一种带有前缀和中缀运算符的语言

然后您可以这样编写
taille
函数:

type infix = ET | OU | U

type prefix = NON | X | G | F

type formule =
  | VRAI
  | Predicat of char
  | Infix of formule * infix * formule
  | Prefix of prefix * formule
let rec taille = function
  | VRAI | Predicat _ -> 1
  | Prefix (_, a) -> 1 + taille a
  | Infix (a, _, b) -> 1 + taille a + taille b

现在,您的类型更细粒度了,您可能会发现在新类型上有意义的新函数

错误消息非常奇怪,OCaml似乎认为整个程序都写在一行上。你在使用哪个编辑器?你在Windows上工作吗?你是对的。实际上,它来自于从pdf文件复制和粘贴代码的事实。这就是为什么编辑认为整个程序都写在一行上的原因。错误消息非常奇怪,OCaml似乎认为整个程序都写在一行上。你在使用哪个编辑器?你在Windows上工作吗?你是对的。实际上,它来自于从pdf文件复制和粘贴代码的事实。这就是为什么编辑认为整个程序只写一行谢谢!它确实完美地回答了我的问题。但是为什么我不能在这里使用析取操作符呢?上下文需要a,而
|
是an中的。在任何情况下,
|
类型为
bool->bool->bool
(不是
formule->formule->?
),谢谢!它确实完美地回答了我的问题。但是为什么我不能在这里使用析取操作符呢?上下文需要a,而
|
是an中的。在任何情况下,
|
的类型为
bool->bool->bool
(不是
formule->formule->?
)。