Consider the following nonsense lambda:
function
| [] -> "Empty list"
| hd::tl -> "Not so empty list"
This works fine. Now I rewrite it as follows:
function
| [] -> "Empty list"
| hd::tl & l -> "Not so empty list"
Again, for nonsense reasons (and I know that I can achieve the same effect by using as
instead of &
, but this all has to do with a code-golf problem that's not pertinent to this question). Now the F# compiler tells me:
warning FS0025: Incomplete pattern matches on this expression. For example, the value '[]' may indicate a case not covered by the pattern(s).
This doesn't make any sense - I am explicitly handling the case of []
in the first rule. I don't see what changed from the first function to the second with respect to []
; neither function's second rule would have matched it yet only the second function gives the warning. All I did was add an additional pattern that matches anything.
Of course, invoking the second function with an empty list does succeed.
Is there a valid reason why this warning occurred, or does the F# pattern validation simply have some quirks? I could see having some cases like this when more advanced patterns are employed, but this seems like a pretty basic one. Even if the problem can't be solved generally, it seems like this type of case would be common enough to merit special handling in the compiler.
I think F# compiler is being practical in this case.
In the end, the second rule can be expressed as a constraint on input list xs
:
xs = hd :: tl && xs = l
F# compiler doesn't seem to explore &&
constraints. This is reasonable because constraints can be arbitrarily complex and the use of &
is quite rare.
We have a similar problem with partial active patterns:
let (|Empty|_|) = function
| [] -> Some()
| _ -> None
let (|NonEmpty|_|) = function
| _ :: _ -> Some()
| _ -> None
// warning FS0025
let f = function
| Empty -> "Empty list"
| NonEmpty -> "Not so empty list"
To fix this issue, you can:
as
instead of &
, which is more appropriate since l
is just a binding.Add a wildcard pattern to the end to eliminate the warning. I usually write
let f =
function
| hd::tl & l -> "Not so empty list"
| _ -> "Empty list"
Suppress the warning using nowarn "25"
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With