null函数的实现

时间:2015-01-14 11:19:46

标签: haskell

我必须学习Haskell大学,因此我开始使用learnyouahaskell.com。我总是使用命令式语言,因此我决定通过编码比我更多地编写Haskell语言。
我开始实施多个功能来处理headtailinit,...等列表 在某些时候,我查找了这些函数的实现,以便与我进行比较,我偶然发现了List.lhs中定义的null函数。

null的实现:

-- | Test whether a list is empty.
null                    :: [a] -> Bool
null []                 =  True
null (_:_)              =  False

我的实施:

mNull :: [a] -> Bool
mNull []        = True
mNull _         = False

我知道即使是这么简单的问题也没有愚蠢的问题:) 所以我的问题是为什么原始实现使用(_:_)而不仅仅是_? 使用(_:_)是否有任何优势,或者是否有任何我不知道的边缘情况? 我无法想象任何优势,因为_能抓住一切。

3 个答案:

答案 0 :(得分:39)

你不能只用你的解决方案来改变条款:

mNull' :: [a] -> Bool
mNull' _  = False
mNull' [] = True

此 即使您传递一个空列表,总是会产生False。因为运行时没有考虑[]子句,所以它立即看到_匹配任何内容。 (GHC会警告你这种重叠的模式。)

另一方面,

null' :: [a] -> Bool
null' (_:_) = False
null' []    = True

仍然可以正常工作,因为(_:_)无法匹配空列表的特定情况。

这本身并没有真正赋予这两个明确的条款优势。但是,在更复杂的代码中,写出所有相互删除的选项有一个好处:如果您忘记了一个选项,编译器也可以向您发出警告!鉴于_可以而且只会处理前一条款未处理的任何案件,即使这些案件实际上并不正确。

答案 1 :(得分:6)

因为_字面意思是除明确指定的模式之外的任何东西。当您指定(_:_)时,它表示可以表示为包含至少1个元素的列表的任何内容,而不会打扰列表实际包含的内容甚至多少元素。由于已存在具有空列表的显式模式的案例,(_:_)也可能被_替换。

但是,将其表示为(_:_)可以让您灵活地甚至不显式传递空列表模式。事实上,这将有效:

-- | Test whether a list is empty.
null                    :: [a] -> Bool    
null (_:_)              =  False
null _                  =  True

Demo

答案 2 :(得分:4)

我将添加左下方所说的内容。这实际上不是列表类型的潜在问题,但通常,数据类型有时会被修改。如果你有一个错误的想法

data FavoriteFood = Pizza
                  | SesameSpinachPancake
                  | ChanaMasala

以后您学会喜欢DrunkenNoodles并将其添加到列表中,您需要扩展所有类型匹配的函数。如果您使用过任何_模式,则需要手动查找;编译器无法帮助你。如果您明确地匹配每件事,您可以打开-fwarn-incomplete-patterns,GHC会告诉您有关您错过的每个地点。