tags:

views:

167

answers:

1

I have this but I got an error:

-- test if a list contains exactly three characters
test :: [Char] -> Bool
test xs   | [_ , _ , _] = True
          | otherwise = False
+11  A: 
Stephan202
Ugh! I was with you right up to the `length` example. It's too close to a classic beginner mistake: writing `length xs == 0` instead of `null xs`.
Norman Ramsey
Or if you want to get fancy, I think the point-free form would be `test = (3 ==) . length`
MatrixFrog
@Norman: hmm, how is `null` going to help here?
Stephan202
@MatrixFrog: Please, no!!! @Stephan: `null` won't help with this problem. My point, which I failed to make clearly, is that many beginners use `length` when they should use either `null` or pattern matching. Encouraging `length` as a solution to this problem is to encourage programming with reckless disregard for costs, and programming that will fail on infinite lists. Your `hasLength` function, on the other hand, is more on the right track. I'm going to edit; if you don't like the edits, roll them back. If you do like them, drop `length` from your answer so I can upvote it :-)
Norman Ramsey
@Norman: thanks for the clarification! Feel free to edit and drop the reference to `length`. While you're at it, add `import Data.List` :)
Stephan202
I choose to add a clear warning above the code which uses `length`, instead of removing it completely; that's more educational. The alternative implementation of `hasLength` doesn't require `import Data.List`.
Stephan202
Norman Ramsey
`hasLength n = not . null . drop (n-1)`
Porges
@Porges: that fails for lists with length `> n`.
Stephan202
@Stephan202: No it doesn't. `let hasLength n = not . null . drop (n-1) in hasLength 3 [1..] == True`
Porges
@Porges: `[1..]` has infinite length, is does *not* have exactly three items. So `hasLength 3 [1..]` should return `False`.
Stephan202
@Stephan: Oh wow, I completely misread the question :(
Porges
Here is a correct version: `hasLength n xs = case drop (n-1) xs of { (_:[]) -> True; _ -> False }`
Porges
@Porges: that code looks very similar to my initial attempt (which used `splitAt`)! Note that `n == 0` should be handled as a special case. Using `drop` has the advantage that the code will not loop on negative inputs, but `haslength n [x]` will yield `True` if `n` is negative.
Stephan202