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->?
)。