20

In defining multiple pattern matches for a function, for instance as follows:

1: takeTree 0 tree                           = Leaf
2: takeTree levels (Leaf)                    = Leaf
3: takeTree levels (Branch value left right) = Branch value (takeTree...

I get two warnings in particular:

Source.hs:1: Warning: Defined but not used: `tree'

Source.hs:2: Warning: Defined but not used: `levels'

I'm not immediately convinced these are useful warnings though. If my code were instead:

1: takeTree 0 _                              = Leaf
2: takeTree _ (Leaf)                         = Leaf
3: takeTree levels (Branch value left right) = Branch value (takeTree...

which, fixes the warnings, I now find it to be far less readable, and obfuscates the semantics of what I expect as input values.

Why is Defined but not used a reasonable warning at all here, when among my exhaustive patterns each argument is in fact used at least once?

DuckMaestro
  • 15,232
  • 11
  • 67
  • 85

3 Answers3

45

The assumption that if something was important enough to name it must be important enough to use is reasonable in many styles of coding.

But you can have your cake and eat it too:

takeTree 0 _tree                           = Leaf
takeTree _levels (Leaf)                    = Leaf
takeTree levels (Branch value left right)  = Branch value (takeTree...

The leading underscore in the name signals to both the human reader and the compiler that the name is not intended to be used in this equation, but the name being longer than a single underscore can still convey more meaning to the human.

Ben
  • 68,572
  • 20
  • 126
  • 174
35

I've made coding errors that were pointed out by this warning. Simplified example:

fun x xs = go xs
  where
    go []      = ... 
    go (y:xs') = f y (go xs)

The recursive call should have xs' as argument, of course, and the "defined but not used" warning will catch that. To me, that's worth the inconvenience of using _ for unused matches.

The compiler is not able to guess your intentions, and the fact that you used the argument in another match does not mean that you didn't mean to use it in the match that generates the warning. After all, you could have used tree, so the warning that you didn't is reasonable.

See also the answer by Ben: you can use _name to use a name but still suppress the warning.

Chris
  • 4,133
  • 30
  • 38
  • 12
    And this kind of mistake is actually not uncommon, nor is it trivial. Because the prime-variants are often very similar to the non-prime ones, it's never a type error and often hard to spot in runtime-debugging, just like it's hard to spot a missing `'` itself. +1 – leftaroundabout Jan 14 '13 at 00:18
9

The compiler's trying to suggest that you use a certain style of coding. If you don't like it (fair enough), there's a way to avoid the problem. See e.g.:

How to [temporarily] suppress "defined but not used" warnings?

As to the substance of the matter (whether or not this is a useful warning): the downside of naming your variables in such situations is it suggests that the names are meaningful to the compiler, when they're not. The upside, as you rightly point out, is that they are meaningful to humans. Basically there's a trade-off and it's quite subjective. The important thing is that you can get the behaviour you want if desired.

Community
  • 1
  • 1
Stuart Golodetz
  • 20,238
  • 4
  • 51
  • 80