为什么使用 null 函数而不是 == [] 来检查 Haskell 中的空列表?
Why use null function instead of == [] to check for empty list in Haskell?
我正在通读 Learn You a Haskell for Great Good! 的 "Starting Out" 章节。它说:
null
checks if a list is empty. If it is, it returns True
, otherwise it returns False
. Use this function instead of xs == []
(if you have a list called xs
)
我在 ghci 中试过:
xs = [] -- and then,
xs == []
null xs
两人都是True
.
我想知道有什么区别。
我应该使用 null
函数而不是 == []
吗?为什么?
你应该使用 null
。在大多数情况下,这无关紧要,但不管怎样,进入它是一个好习惯,因为偶尔你可能想检查 non-comparable 事物的列表是否为空。这是一个显示这种差异的简短示例:
> 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 <b>Eq a =></b> Eq [a] where
[] == [] = True
(x:xs) == (y:ys) = <b>x == y</b> && xs == ys
_ == _ = False
这意味着如果 x
是 IO Int
的列表,则不能使用 x == []
。
null :: [a] -> Bool
on the other hand, uses pattern matching. This is implemented as:
null :: [a] -> Bool
null [] = True
null (_:_) = False
所以不管列表的元素是什么类型,它总是会进行类型检查。
除了到目前为止给出的好的答案,null
实际上有类型
null :: Foldable t => t a -> Bool
我不知道你是否在 LYAH 中使用过类型类,但简而言之,null
不仅可以用于列表,还可以用于实现 [=14] 的任何数据结构=].
也就是说在Map
or a Set
上使用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
函数:
的更多信息
我正在通读 Learn You a Haskell for Great Good! 的 "Starting Out" 章节。它说:
null
checks if a list is empty. If it is, it returnsTrue
, otherwise it returnsFalse
. Use this function instead ofxs == []
(if you have a list calledxs
)
我在 ghci 中试过:
xs = [] -- and then,
xs == []
null xs
两人都是True
.
我想知道有什么区别。
我应该使用 null
函数而不是 == []
吗?为什么?
你应该使用 null
。在大多数情况下,这无关紧要,但不管怎样,进入它是一个好习惯,因为偶尔你可能想检查 non-comparable 事物的列表是否为空。这是一个显示这种差异的简短示例:
> 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 <b>Eq a =></b> Eq [a] where
[] == [] = True
(x:xs) == (y:ys) = <b>x == y</b> && xs == ys
_ == _ = False
这意味着如果 x
是 IO Int
的列表,则不能使用 x == []
。
null :: [a] -> Bool
on the other hand, uses pattern matching. This is implemented as:
null :: [a] -> Bool null [] = True null (_:_) = False
所以不管列表的元素是什么类型,它总是会进行类型检查。
除了到目前为止给出的好的答案,null
实际上有类型
null :: Foldable t => t a -> Bool
我不知道你是否在 LYAH 中使用过类型类,但简而言之,null
不仅可以用于列表,还可以用于实现 [=14] 的任何数据结构=].
也就是说在Map
or a Set
上使用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
函数: