null函数的实现

Tor*_*enJ 26 haskell

我必须学习Haskell大学,因此我开始使用learnyouahaskell.com.
我总是使用命令式语言,因此我决定通过编码比其他语言更多地编写Haskell.
我开始实行多种功能与列表,如工作head,tail,init,...
在某些时候,我抬头一看,这些功能的实现来比较我的,我偶然发现在定义空函数List.lhs.

null的实现:

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

我的实施:

mNull :: [a] -> Bool
mNull []        = True
mNull _         = False
Run Code Online (Sandbox Code Playgroud)

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

lef*_*out 39

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

mNull' :: [a] -> Bool
mNull' _  = False
mNull' [] = True
Run Code Online (Sandbox Code Playgroud)

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

另一方面,

null' :: [a] -> Bool
null' (_:_) = False
null' []    = True
Run Code Online (Sandbox Code Playgroud)

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

这本身并没有真正赋予这两个明确的条款优势.但是,在更复杂的代码中,写出所有相互排斥的选项有一个好处:如果你忘记了一个选项,编译器也可以警告你!虽然_能够并且只会处理前面条款未处理的任何案件,即使这实际上并不正确.


shr*_*t18 6

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

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

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

演示


dfe*_*uer 5

我将补充 leftaroundabout 所说的内容。对于列表类型来说,这并不是真正的潜在问题,但一般来说,数据类型有时会被修改。如果你有一个不周全的想法

data FavoriteFood = Pizza
                  | SesameSpinachPancake
                  | ChanaMasala
Run Code Online (Sandbox Code Playgroud)

当您学会喜欢DrunkenNoodles并将其添加到列表中时,所有与该类型模式匹配的函数都需要扩展。如果您使用过任何_模式,则需要手动查找它们;编译器无法帮助你。如果您明确匹配了所有内容,则可以打开-fwarn-incomplete-patternsGHC,GHC 会告诉您错过的每个位置。