Haskell下划线与显式变量

时间:2015-11-24 20:03:51

标签: haskell

我已经学习Haskell几周了,我对使用下划线(_)作为函数参数有疑问。我想用一个具体的例子可以更好地问我的问题。假设我想定义一个函数,该函数根据提供的索引提取列表元素 - 是的,我意识到(!!)已经预定义了。我可以定义函数的两种方式(我确定还有更多)如下:

版本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)

版本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)

这两个版本显然非常相似。两者之间的唯一区别是使用显式变量或下划线。对我来说_意味着字面上可以写任何东西,而像n这样的显式变量使得参数必须是整数更明显。出于这个原因,我更喜欢第1版;但(!!)的GHC源代码与版本2类似。第二版是否具有功能优势?如果没有,那么“硬核”Haskell程序员会不会对版本1有疑问?我理解使用一致的编写代码的方法的重要性,因此我尝试遵循用于特定语言编程的“不成文规则”。这是一个我非常喜欢第一个版本的例子,我认为它不会让代码更难阅读。我不知道这是因为我的纯数学背景还是什么,但我想听听你更多经验丰富的人--Haskell兽医认为。

1 个答案:

答案 0 :(得分:18)

  

第二个版本有功能优势吗?

我认为他们没有任何操作上的差异。但我发现第二个版本更具可读性。 _表示根本没有使用它。因此,在阅读代码时,我可以忽略它,只关注其他参数。在第一个版本中,我会认为n已定义,但作者可能忘了使用它?或者也许这个论点是不必要的。第二个版本只是避免了这种心理超负荷。但这只是我的意见。 :)

事实上,如果您启用警告标志(-Wall)并编译代码,它将为您的第一个版本发出警告:

[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’