假设我想检查Haskell中一个守卫中的列表是否为空,有两个选项:
length list == 0
list == []
这两个逻辑测试中的哪一个更有效?我倾向于说空列表测试因为依赖于更基本的构造而不是前奏函数length
但是我不确定。
答案 0 :(得分:14)
length list == 0
需要遍历整个列表以获取其长度,这意味着它是 O(n)。 list == []
对元素类型产生Eq
约束。 null list
以恒定时间运行,没有类型类约束。
然而,有一个巧妙的做法是做length list == 0
这样的事情,它的优势在于它可以很好地概括为length list1 == length list2
而无需通过更长的列表:你可以使用genericLength
自然数字的充分惰性表示,以便比较只会强制遍历较短的列表。
一个例子是使用the Natural
type:
import Data.Number.Natural
import Data.List (genericLength)
nats :: [Int]
nats = iterate succ 0
areThereTenNats :: Bool
areThereTenNats = genericLength nats >= (10 :: Natural)
答案 1 :(得分:7)
正如其他人所指出的那样,检查列表是否为空(而不是更多)的最佳方法是使用
null :: Foldable f => f a -> Bool
可以在
类型中使用null :: [a] -> Bool
如果你想检查一个列表是否为空,因为你想要查看它的元素,你通常应该使用模式匹配:
f [] = something
f (x : xs) = something using x and/or xs
如果你想比较两个列表的长度(而不是更多),最好的方法通常是
compareLength :: [a] -> [b] -> Ordering
compareLength [] [] = EQ
compareLength [] (_ : _) = LT
compareLength (_ : _) [] = GT
compareLength (_ : xs) (_ : ys) =
compareLength xs ys
检查列表长度与特定数字的比较的最佳方法是
compareToLength :: Foldable f
=> f a -> Int -> Ordering
compareToLength = foldr go (compare 0) where
go _ r n | n <= 0 = GT
| otherwise = r $! n - 1
答案 2 :(得分:4)
您可以使用null list
检查列表是否为空,并返回布尔值。
Prelude> null []
True
Prelude> null [1]
False
Prelude> null ""
True
Prelude> null "Test"
False