Haskell: Gluing a char and a list together?
So I have this code here:
toWords :: String -> [String]
toWords "" = []
toWords (nr1 : rest)
| nr1 == ' ' = toWords rest
| otherwise = [nr1] : toWords rest
The "toWords" function should simply remove all spaces and return a list with all the words. But this happens:
*Main> toWords "How are you?"
["H","o","w","a"开发者_如何学编程,"r","e","y","o","u","?"]
Is this just me, or you are trying to re-invent "words" function from Prelude?
Your type should be String -> [String] or [Char] -> [[Char]].
Your input is a string (a list of chars) your output a list of string (a list of chars of chars).
Your type here means it maps a string to ANY type, this is not true.
Edit: alternatively you can use:
splitBy :: [a] -> a -> [[a]]
splitBy [] sep = []
splitBy (nr1 : rest) if nr1 == sep then splitBy rest sep else nr1 : (splitBy rest sep)
Which is polymorphic and splits a list by any separator. (code not tested though) so splitBy "string of words" ' '
should return ["string","of","words"].
FINALLY, this was annoying and had an obvious and stupid error of [] in lieu of [[]] the functional version is:
splitBy [] sep = [[]]
splitBy (nr1 : rest) sep = if nr1 == sep
then [] : splitBy rest sep
else (nr1 : head (splitBy rest sep)) : tail (splitBy rest sep)
Such that: splitBy "List of things" ' ' ===> ["list","of","things"]
Think about what this does:
It iterates through each character in the string.
| nr1 == ' ' = toWords rest
If the character is a space, it skips that character.
| otherwise = [nr1] : toWords rest
Otherwise it creates a string containing only that character, then continues doing so to the rest of the characters in the string.
What you want is to accumulate the characters in the word into a single list rather than creating a new list for each one.
Here's an example of how you could do it:
toWords "" = []
toWords (' ':rest) = toWords rest
toWords text = let (word, rest) = break (== ' ') text
in word : toWords rest
Two questions - firstly, why is your output polymorphic? It seems like it's invariably going to be a list of String
rather than a list of a
. I'm not that familiar with the Haskell type inference internals; try changing the signature to String -> String
or String -> [Char]
and see if it then works.
Secondly, when you do this it should become clear that your implementation is a little off; even if it did work, it would simply return your original string with all the spaces removed.
If you do want to return a list of strings, you'll need to have a helper function that builds up the current word so far, and then adds that whole word to the output list when the current character is a string. Since it seems like you're doing this to learn (else, just use the Prelude function) I won't give a listing but it shouldn't be too hard to figure out from here.
精彩评论