解决脆弱模式匹配的建议

nlu*_*oni 4 ocaml functional-programming pattern-matching

我经常需要匹配应该具有相同构造函数的元组元组.最后,笼子_,_总是炙手可热.这当然是脆弱的,添加到该类型的任何其他构造函数将完全编译.我目前的想法是连接第一个但不是第二个参数的匹配.但是,还有其他选择吗?

例如,

type data = | States of int array 
            | Chars  of (char list) array

let median a b = match a,b with
    | States xs, States ys ->
        assert( (Array.length xs) = (Array.length ys) );
        States (Array.init (Array.length xs) (fun i -> xs.(i) lor ys.(i)))
    | Chars xs, Chars ys -> 
        assert( (Array.length xs) = (Array.length ys) );
        let union c1 c2 = (List.filter (fun x -> not (List.mem x c2)) c1) @ c2 in
        Chars (Array.init (Array.length xs) (fun i -> union xs.(i) ys.(i)))
    (* inconsistent pairs of matching *)
    | Chars  _, _
    | States _, _ -> assert false
Run Code Online (Sandbox Code Playgroud)

Pas*_*uoq 8

您可以使用下面稍短的图案:

| (Chars _| States _), _ -> assert false
Run Code Online (Sandbox Code Playgroud)

实际上,你可以让编译器为你生成它,因为它仍然有点乏味.输入以下内容并编译:

let median a b = match a,b with
| States xs, States ys ->
    assert( (Array.length xs) = (Array.length ys) );
    States (Array.init (Array.length xs) (fun i -> xs.(i) lor ys.(i)))
| Chars xs, Chars ys -> 
    assert( (Array.length xs) = (Array.length ys) );
    let union c1 c2 = (List.filter (fun x -> not (List.mem x c2)) c1) @ c2 in
    Chars (Array.init (Array.length xs) (fun i -> union xs.(i) ys.(i)))
Run Code Online (Sandbox Code Playgroud)

警告8:此模式匹配并非详尽无遗.以下是不匹配的值的示例:(Chars _,States _)

您现在可以将建议的模式复制粘贴回代码中.这通常是我为具有数十个构造函数的类型生成非脆弱的catch-all模式的方法.您可能需要多次启动编译器,但它仍然比自己键入它们更快.