如何检测列表中Haskell中是否有3个项目?

unj*_*nj2 1 syntax haskell list

我有这个,但我收到一个错误:

-- test if a list contains exactly three characters
test :: [Char] -> Bool
test xs   | [_ , _ , _] = True
          | otherwise = False
Run Code Online (Sandbox Code Playgroud)

Ste*_*202 12

模式匹配发生在垂直条的左侧.从而:

test :: [Char] -> Bool
test [_, _, _] = True
test _         = False
Run Code Online (Sandbox Code Playgroud)

正如Norman Ramsey在下面正确指出的那样,下面的代码不是一个强大的替代解决方案(因为它应用于(长)有限列表时非常低效,并且不会在无限列表上停止)因此应该使用:

test :: [Char] -> Bool
test xs = length xs == 3
Run Code Online (Sandbox Code Playgroud)

而且,length xs == 0应该总是替换null xs.

编辑:自然产生的问题是:我们如何概括这一点?如果我们想测试一个列表是否只有n个元素怎么办?如果输入可能是无限的怎么办?这是一个解决方案,其中成本是n列表的长度或者是列表的长度,以较小者为准 - 这是一种有效的解决方案,渐近地,正如我们可能希望的那样:

hasLength :: Int -> [a] -> Bool
hasLength n []     = n == 0
hasLength 0 (x:xs) = False
hasLength n (x:xs) = hasLength (n-1) xs
Run Code Online (Sandbox Code Playgroud)

用法:

*Main> hasLength 3 [1..2]
False
*Main> hasLength 3 [1..3]
True
*Main> hasLength 3 [1..4]
False
*Main> hasLength 3 [1..] 
False
Run Code Online (Sandbox Code Playgroud)

以负长度调用此函数是不安全的 ; 如果列表是无限的,则函数不会终止,如果列表是有限的,它将返回False与列表长度成比例的成本.一个简单的解决方法是提前检查(仅在第一次调用时)n非负,但这个修复会使代码变得丑陋.

  • @MatrixFrog:拜托,不!@Stephan:`null`对这个问题无济于事.我的观点,我没有说清楚,是许多初学者在使用`null`或模式匹配时使用`length`.鼓励"长度"作为解决这个问题的方法是鼓励编程,不顾一切地忽视成本,以及在无限列表上失败的编程.另一方面,你的`hasLength`功能更加正确.我要编辑; 如果您不喜欢这些编辑,请将它们回滚.如果你喜欢它们,请从你的答案中删除`length`,这样我就可以投票了:-) (2认同)