繁体   English   中英

为什么使用null函数而不是== []来检查Haskell中的空列表?

[英]Why use null function instead of == [] to check for empty list in Haskell?

我正在阅读“ 了解你是一个很好的Haskell ”的“开始”一章 它说:

null检查列表是否为空。 如果是,则返回True ,否则返回False 使用此函数而不是xs == [] (如果您有一个名为xs的列表)

我试过ghci:

xs = []      -- and then,

xs == []
null xs

两者都是True

我想知道有什么区别。

我应该使用null函数而不是== []以及为什么?

你应该使用null 在大多数情况下它并不重要,但无论如何都是一个好习惯,因为偶尔你可能想检查一下不可比的东西是否为空。 这是一个简短明了的例子,展示了这种差异:

> null [id]
False
> [id] == []
<interactive>:1:1: error:
    • No instance for (Eq (a0 -> a0)) arising from a use of ‘==’
        (maybe you haven't applied a function to enough arguments?)
    • In the expression: [id] == []
      In an equation for ‘it’: it = [id] == []

它们是有区别的。 为了使用x == [] ,列表元素的类型应该是Eq类型类的成员。 实际上,检查两个列表的相等性是由实例声明定义的:

instance Eq a => Eq [a] where
    []     == []      =  True
    (x:xs) == (y:ys)  =  x == y  &&  xs == ys
    _      == _       =  False

这意味着如果x是例如IO Int的列表,则不能使用x == []

null :: [a] -> Bool另一方面使用模式匹配。 实现为

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

因此,无论列表的元素是什么类型,它总是会进行类型检查。

除了到目前为止给出的好答案, null实际上有类型

null :: Foldable t => t a -> Bool

我不知道你是否已经获得了LYAH中的类型类,但缺点是null不仅可以用于列表,还可以用于任何实现null数据结构。

这就是说在MapSet上使用null也是有效的。

> null Map.empty
True
> null (Map.singleton 1)
False
> null Set.empty
True
> null (Set.singleton 1)
False
> null []
True
> null [1]
False

我认为编写需要这种通用的函数并不常见,但默认编写更通用的代码并没有什么坏处。

旁注

在许多情况下,您最终会想要使用null类的函数来对列表(或其他数据结构)执行条件行为。 如果您已经知道您的输入是特定的数据结构,那么在其空案例上进行模式匹配会更加优雅。

相比

myMap :: (a -> b) -> [a] -> [b]
myMap f xs
  | null xs = []
myMap f (x:xs) = f x : myMap f xs

myMap' :: (a -> b) -> [a] -> [b]
myMap' f [] = []
myMap' f (x:xs) = f x : myMap' f xs

一般来说,如果有意义的话,你应该尝试更喜欢模式匹配。

过滤所有空列表的简单函数也会失败:

withoutEmpty = filter (== [])

那将是:

withoutEmpty = filter null

注意:

withoutEmpty ls = filter (==[]) ls

工作得很好,但重要的是,在某些情况下,如另一个人可能会失败。

另外看看@cole的答案,它补充了这里的所有答案,类型类Foldable在那里实现了null函数:

这里查看可折叠的更多信息

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM