2010-04-04 34 views
0

我想知道人们如何处理SML/NJ编译器中的非穷举匹配警告。例如,我可以定义一个数据类型SML/NJ未完成匹配

datatype DT = FOO of int | BAR of string 

,然后让我知道一个功能只FOOS

fun baz (FOO n) = n + 1 

编译器会给出警告

stdIn:1.5-1.24 Warning: match nonexhaustive 
      FOO n => ... 
val baz = fn : DT -> int 

我不希望看到针对我完成的不完整匹配的警告,因为之后我必须扫描输出以查找可能实际上是错误的警告。我可以写这样的功能

fun baz (FOO n) = n + 1 
    | baz _ = raise Fail "baz" 

但这会使代码杂乱无章。人们通常在这种情况下做什么?

回答

3

您可以设置以下编译器标志配置非详尽的匹配警告的警告级别:

  • Compiler.Control.MC.matchNonExhaustiveWarn
  • Compiler.Control.MC.matchNonExhaustiveError

如果这两个都设置为false,则不会生成警告。不幸的是,这将关闭此错误的所有实例的警告,这可能不是您想要的,因为它会移除此安全措施。

(注:您只要在代码中设置这些为false)

更多信息,可以发现here。第46项具体描述了你的警告。

2

您必须覆盖所有的情况,以便您确定函数如何处理其整个域或遵从警告。最后的选择是首先修改通过函数提供的值,以便在调用者中完成解构。

3

正如丹尼尔所说,你可以关掉警告,但我不会推荐。

如果您可以调整数据类型,以便函数能够在允许的整个值范围内运行,那么最好。其次,最好是继续前进,并用错误“混乱”代码,使其明确发生了什么(并允许更有意义的运行时错误)。

+0

你能否提供一些关于如何更改编译器标志的信息? – 2014-02-06 00:15:51

1

我想如果你这么做了很多,你需要重新考虑一下你的数据类型。为什么将Foo和Baz分组在一起,如果它们不是同一类型的对象?如果他们是构建同一个对象的不同方式,那么你会期望在Foo上工作的函数也能够在Baz上做一些明智的事情。如果你有一个带有构造函数Car和Bike的类型Vehicle,但你只想在Cars上做一些操作,如果你的代码很大,那么正确的做法可能是将Car的定义分开并且改变你使用的所有地方车辆,但期望只有汽车直接使用汽车。

1

与其他答案一样,更改数据类型以产生完全匹配更为简洁。在这种情况下,您可能会更改DT类型,或者您可以从baz更改返回类型。例如:

datatype DT = FOO of int | BAR of string 
fun baz (FOO n) = SOME (n + 1) 
    | baz _  = NONE 

然后baz有型val baz = fn : DT -> int option,你不必担心处理由baz引发的错误。