Haskell:将char和列表粘合在一起?

时间:2010-05-19 15:11:42

标签: haskell

所以我在这里有这个代码:

toWords :: String -> [String]
toWords "" = []
toWords (nr1 : rest)
    | nr1 == ' ' = toWords rest
    | otherwise = [nr1] : toWords rest

“toWords”函数应该只删除所有空格并返回包含所有单词的列表。但这种情况发生了:

  

*主> toWords“你好吗?”

     

[ “H”, “O”, “W”, “一个”, “R”, “E”, “Y”, “O”, “U”, “?”]

4 个答案:

答案 0 :(得分:5)

这只是我,还是你试图从Prelude重新发明“单词”功能?

答案 1 :(得分:4)

您的类型应为String - > [String]或[Char] - > [[字符]。

您的输入是一个字符串(字符列表)您的输出字符串列表(字符列表)。

此处的类型表示它将字符串映射到ANY类型,但事实并非如此。

编辑:或者您可以使用:

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"]

答案 2 :(得分:1)

想想这是做什么的:

它遍历字符串中的每个字符。

| nr1 == ' ' = toWords rest

如果角色是空格,则会跳过该角色。

| otherwise = [nr1] : toWords rest

否则它会创建一个只包含该字符的字符串,然后继续对字符串中的其余字符执行此操作。

您想要的是将单词中的字符累积到单个列表中,而不是为每个列表创建新列表。

以下是您如何做到这一点的示例:

toWords "" = []
toWords (' ':rest) = toWords rest
toWords text       = let (word, rest) = break (== ' ') text
                     in word : toWords rest

答案 3 :(得分:0)

两个问题 - 首先,为什么你的输出是多态的?似乎它总是会成为String的列表,而不是a的列表。我不熟悉Haskell类型的推理内部结构;尝试将签名更改为String -> StringString -> [Char],然后查看它是否有效。

其次,当你这样做时,应该清楚你的实现有点偏;即使它确实有效,它也只会返回原始字符串并删除所有空格。

如果你想要返回一个字符串列表,你需要有一个帮助函数来构建到目前为止的当前单词,然后将整个单词添加到输出列表中当前字符是一个字符串。既然你好像要这样学习(否则,只使用Prelude功能)我不会给出一个列表,但是从这里找出它应该不会太难。