Haskell 哈斯克尔:把字符和列表粘在一起?
我这里有一个代码:Haskell 哈斯克尔:把字符和列表粘在一起?,haskell,Haskell,我这里有一个代码: toWords :: String -> [String] toWords "" = [] toWords (nr1 : rest) | nr1 == ' ' = toWords rest | otherwise = [nr1] : toWords rest “toWords”函数只需删除所有空格并返回包含所有单词的列表。但这种情况会发生: *Main>toWords“你好吗?” [“H”、“o”、“w”、“a”、“r”、“e”、“
toWords :: String -> [String]
toWords "" = []
toWords (nr1 : rest)
| nr1 == ' ' = toWords rest
| otherwise = [nr1] : toWords rest
“toWords”函数只需删除所有空格并返回包含所有单词的列表。但这种情况会发生:
*Main>toWords“你好吗?”
[“H”、“o”、“w”、“a”、“r”、“e”、“y”、“o”、“u”和“?”]
这仅仅是我,还是你正试图从Prelude中重新发明“words”函数?两个问题——首先,为什么你的输出是多态的?它似乎总是一个
字符串的列表,而不是一个字符串的列表。我不太熟悉Haskell类型的推理内部结构;尝试将签名更改为String->String
或String->[Char]
,然后查看是否有效
第二,当你这样做的时候,你应该清楚地看到你的实现有点不顺利;即使它确实有效,它也会简单地返回原始字符串,并删除所有空格
如果确实要返回字符串列表,则需要有一个helper函数来构建当前单词,然后在当前字符为字符串时将整个单词添加到输出列表中。因为您这样做似乎是为了学习(否则,只需使用Prelude函数),所以我不会给出一个列表,但从这里应该不难理解。您的类型应该是String->[String]或[Char]->[[Char]]
您的输入是一个字符串(字符列表),您的输出是一个字符串列表(字符列表)
这里的类型意味着它将字符串映射到任何类型,这不是真的
编辑:或者,您可以使用:
splitBy :: [a] -> a -> [[a]]
splitBy [] sep = []
splitBy (nr1 : rest) if nr1 == sep then splitBy rest sep else nr1 : (splitBy rest sep)
它是多态的,并通过任何分隔符拆分列表。(代码未经测试)因此splitBy“string of words”'
应返回[“string”、“of”、“words”]
最后,这是一个恼人的问题,它有一个明显而愚蠢的错误[]代替了[]。功能版本是:
splitBy [] sep = [[]]
splitBy (nr1 : rest) sep = if nr1 == sep
then [] : splitBy rest sep
else (nr1 : head (splitBy rest sep)) : tail (splitBy rest sep)
这样:splitBy“List of things”''==>[“List”,“of”,“things”]
思考一下它的作用:
它遍历字符串中的每个字符
| nr1 == ' ' = toWords rest
如果字符是空格,则跳过该字符
| otherwise = [nr1] : toWords rest
否则,它将创建一个仅包含该字符的字符串,然后继续对该字符串中的其余字符执行此操作
| nr1 == ' ' = toWords rest
您想要的是将单词中的字符累积到单个列表中,而不是为每个字符创建一个新列表
下面是一个示例,说明如何做到这一点:
toWords "" = []
toWords (' ':rest) = toWords rest
toWords text = let (word, rest) = break (== ' ') text
in word : toWords rest
哇,我不知道。但我仍然好奇我的代码有什么问题:)您打印的错误消息与您的代码不匹配。您的代码有nr1:toWords rest
,但错误消息提到[nr1]:toWords rest
@Tom Lokhorst您是对的,错误消息是错误的。谢谢:)splitBy的类型实际上是(等式a)=>[a]->a->[[a]]]
。它只适用于Eq的实例。在实践中可能不是什么问题——只是指出它。