问题
I've been learning Haskell for a few weeks, and I have a question about the use of the underscore (_
) as a function parameter. I think my question will be better asked with a specific example. Let's say I want to define a function that extracts the element of a list based on the provided index—yes, I realize (!!)
is already pre-defined. The two ways that I can define the function (I'm sure there are more) are the following:
Version 1
indexedElement :: [a] -> Int -> a
indexedElement xs n | n < 0 = error "Index can not be negative."
indexedElement [] n = error "Index must be smaller than the length of the list."
indexedElement (x:xs) 0 = x
indexedElement (x:xs) n = indexedElement xs (n - 1)
Version 2
indexedElement :: [a] -> Int -> a
indexedElement _ n | n < 0 = error "Index can not be negative."
indexedElement [] _ = error "Index must be smaller than the length of the list."
indexedElement (x:_) 0 = x
indexedElement (_:xs) n = indexedElement xs (n - 1)
The two versions are obviously very similar. The only difference between the two is the use of an explicit variable or an underscore. To me _
means that literally anything can be written there while an explicit variable like n
makes it more obvious that the argument must be an integer. For that reason, I prefer Version 1; but the GHC source code for (!!)
is written like Version 2. Is there a functional advantage of the second version? If not, would "hardcore" Haskell programmers take issue with Version 1? I understand the importance of having a consistent way of writing code, so I try to follow the "unwritten rules" for programming in a particular language. This is an example where I much prefer the first version though, and I don't think it makes the code any more difficult to read. I don't know if it's due to my background in pure math or what, but I'd like to hear what you more-seasoned-Haskell vets think.
回答1:
Is there a functional advantage of the second version?
I don't think they have any operational difference. But I find the second version more readable. _
indicates that it isn't used at all. So while reading the code, I can just ignore it and just concentrate on the other parameters. Whereas in the first version, I will be thinking that n
is defined but maybe the author forgot to use it ? Or maybe the argument isn't required. The second version just avoids this kind of mental overload. But this is just my opinion. :)
In fact, if you enable the warning flag (-Wall
) and compile your code, it will throw warning for your first version:
[1 of 1] Compiling Main ( code.hs, code.o )
code.hs:2:16: Warning: Defined but not used: ‘xs’
code.hs:3:19: Warning: Defined but not used: ‘n’
code.hs:4:19: Warning: Defined but not used: ‘xs’
code.hs:5:17: Warning: Defined but not used: ‘x’
code.hs:8:17: Warning: Defined but not used: ‘xs’
来源:https://stackoverflow.com/questions/33902767/haskell-underscore-vs-explicit-variable