2010-03-19 41 views
1

我有这个,但我得到了一个错误:如何检测Haskell中的列表是否包含3个项目?

-- test if a list contains exactly three characters 
test :: [Char] -> Bool 
test xs | [_ , _ , _] = True 
      | otherwise = False 
+0

我不得不说,我更喜欢'[_,_,_]'到'[_,_,_]'。 – MatrixFrog 2010-03-19 21:10:42

+0

你有什么错误? – 2010-03-19 21:18:36

+0

这里的答案比我要求的要多。谢谢。 – unj2 2010-03-19 22:15:28

回答

12

模式匹配发生在左侧竖线的侧。因此:

test :: [Char] -> Bool 
test [_, _, _] = True 
test _   = False 

Norman Ramsey下面正确地指出,下面的代码是健壮替代的解决方案(因为它是当施加到(长)的有限列表非常低效和无限列表不停止),并应因此使用:

test :: [Char] -> Bool 
test xs = length xs == 3 

此外,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 

用法:

*Main> hasLength 3 [1..2] 
False 
*Main> hasLength 3 [1..3] 
True 
*Main> hasLength 3 [1..4] 
False 
*Main> hasLength 3 [1..] 
False 

这是不安全调用此函数负长度;如果列表是无限的,函数将不会终止,并且如果列表是有限的,它将返回False,其成本与列表的长度成比例。一个简单的解决办法是事先检查(仅在第一次通话时)n是非负的,但是这种修复会使代码变得难看。

+0

呃!我和你在一起,直到“长度”的例子。这太类似于经典的初学者错误:写'length xs == 0'而不是'null xs'。 – 2010-03-19 21:16:18

+0

或者如果你想要看起来,我认为这个无点形式应该是'test =(3 ==)。长度' – MatrixFrog 2010-03-19 21:20:47

+0

@Norman:嗯,'null'怎么会在这里帮忙? – Stephan202 2010-03-19 21:28:18

相关问题