我已阅读(并且还推断)计算列表长度对Haskell的性能不利。但是,我的程序中有很长的列表,我的要求是发现如果长度大于或小于某个数字X.
他们已经在Haskell中为这些谓词构建了什么东西?或者我不得不求助于手动循环。
答案 0 :(得分:7)
在vanilla列表中,您可以使用drop
:
cmpLen :: Int -> [a] -> Ordering
cmpLen n xs
| n < 0 = GT
| otherwise = case drop (n-1) xs of
[] -> GT
[_] -> EQ
_ -> LT
然而,这仍然需要n
的值(不是渐近分析的典型大小!)。如果您打算经常这样做,您可以从Okasaki获取一个提示并构建一个新的结构来缓存您想要高效的操作。我之前想过几次,在这些情况下发现以下类型的界面很方便:
type LenList a = (Sum Word, [a])
singleton x = (1, [x])
cons x = (singleton x<>)
length = getSum . fst
elems = snd
请注意,由于LenList a
已经是Monoid
,因此您可以免费获得一些常规操作,例如有一个名为LenList a
的空mempty
,(<>)
给出了连接。某些操作(特别是产生无限列表的操作)将无法实现此类型。但是,您需要为每个施工操作支付O(1)价格,以便询问其中一个O(1)的长度,这在许多情况下可能是一个很好的权衡。