在特定行

时间:2016-10-23 15:20:37

标签: ocaml

我目前正在构建一个项目,它允许不同类型的函数,具有不同数量的参数(但它们都是相同类型的)。为了定义这些函数,我为每个函数使用了这个代码:

let {name} [a; b; {...}] =
  {...}

我的代码确保列表中的元素数量是正确的,如果不是这种情况,我只会发生运行时错误。但我有一个警告,我想要隐藏,因为我知道这种模式匹配并非详尽无遗,而且我不希望看到警告不会警告我有关真正的错误我有制成。

另一方面:如果存在像Dafny(来自微软)这样的语言,那就是功能性的,我会很乐意尝试这种语言。

编辑:如果没有办法,请回答说明。在这种情况下,我将构建一个过滤掉这些警告的命令行工具。 (但这可能会抹掉所有格式......)

2 个答案:

答案 0 :(得分:6)

你很有可能知道,你可以这样写:

let name = function
    | [a; b; ... ] -> { ... }
    | _ -> failwith "not possible"

但您可以(如果您坚持)通过在[@warning "-8"]和函数名称之间写let来禁用警告。

$ cat warn.ml
let f [a; b] = a + b
$ ocamlc -c warn.ml
File "warn.ml", line 1, characters 6-20:
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
(_::_::_::_|_::[]|[])

$ cat nowarn.ml
let [@warning "-8"] f [a; b] = a + b
$ ocamlc -c nowarn.ml
$ 

<强>更新

我找到了一种方法来重新启动功能正文的警告,虽然看起来很笨重:

$ cat semiwarn.ml
let [@warning "-8"] f [a; b] =
    begin [@warning "+8"]
    let a' =
    match a with
        | 0 -> 14
        | 1 -> 15
    in
    a' + b
    end
$ ocamlc -c semiwarn.ml
File "semiwarn.ml", line 4, characters 4-52:
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
2

如您所见,函数正文中存在匹配警告,但函数参数没有警告。

总的来说,如果你希望人们阅读代码,这似乎有点混乱,不是一个好的选择。

答案 1 :(得分:1)

  

另一方面:如果存在像Dafny(来自微软)这样的语言,那就是功能性的,我很乐意尝试那种语言。

OCaml的类型系统足以表达这种类型的不变量:您可以使用GADT定义长度索引列表。

您必须首先介绍类型级自然数:

type zero    = Zero
type 'a succ = Succ

他们并不完全是类型级自然数,因为您可以编写非感性表达式,例如int list succ,但它们足够接近我们的目的:我们类型长度的数据构造函数 - 索引列表将强制该长度仅由succ和最后的zero组成。我还必须为这些类型中的每一个提供reasons outside the scope of this answer的构造函数。

然后,您可以定义('a, 'n) vector类似'a list的{​​{1}}长度'n,如下所示:

type ('a, _) vector =
  | []   : ('a, zero) vector
  | (::) : 'a * ('a, 'n) vector -> ('a, 'n succ) vector

通过使用[](::)作为构造函数,您可以在定义list时重用param语法。我希望有可能写(int, 4) vector,但我找不到办法。

let param : (int, zero succ succ succ succ) vector = [3;1;0;4]

或者,您可以让OCaml推断出param_中的参数。您没有明确说明不变量,但会在每个使用点进行检查。

let param_ : (int, _) vector = [3;1;0;4]
let () = match param_ with
 (*  [x;y;z] -> print "Argh!\n" (* This doesn't typecheck *)*)
  [x;y;z;t] -> print_string "Yeah!\n"