开发者

How do you detect if a list has exactly 3 items in Haskell?

I have this but I got an error:

-- test if a li开发者_JS百科st contains exactly three characters
test :: [Char] -> Bool
test xs   | [_ , _ , _] = True
          | otherwise = False


Pattern matching happens on the left side of the vertical bar. Thus:

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

As Norman Ramsey rightly notes below, the following code is not a robust alternative solution (because it is very inefficient when applied to (long) finite lists and does not halt on infinite lists) and should thus not be used:

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

Moreover, length xs == 0 should always be replaced with null xs.

Edit: the question which naturally arises is: how do we generalize this? What if we want to test whether a list has exactly n elements? What if the input may be infinite? Here's a solution where the cost is either n or the length of the list, whichever is smaller—and that's as efficient a solution, asymptotically, as we can possibly hope for:

hasLength :: Int -> [a] -> Bool
hasLength n []     = n == 0
hasLength 0 (x:xs) = False
hasLength n (x:xs) = hasLength (n-1) xs

Usage:

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

It is unsafe to call this function with a negative length; if the list is infinite, the function won't terminate, and if the list is finite, it will return False with cost proportional to the length of the list. An easy fix would be to check in advance (on the first call only) that n is nonnegative, but this fix would ugly up the code.


I'd write something like

hasLength3 :: [a] -> Bool
hasLength3 xs = xs `hasLength` 3

hasLength :: [a] -> Int -> Bool
hasLength = foldr go stop
  where
    go _ r n = n > 0 && r (n - 1)
    stop n = n == 0


main = do
  a:b:c:[] <- pure "123"  -- fails in runtime in MonadFail if they are not exactly 3
  print a >> print b >> print c
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜