从字符串到列表的单词

时间:2017-12-23 10:58:35

标签: haskell

我正在尝试编写一个Haskell函数,该函数将读取一个字符串并返回一个列表,其中包含保存在其中的字符串中的单词。

我是这样做的:

toWordList :: String -> [String]
toWordList = do
[ toLower x | x <- str ]
    let var = removePunctuation(x)
        return (words var)  

但是我收到了这个错误:

Test1.hs:13:17: error: parse error on input 'let'
   |
13 |                 let var = removePunctuation(x)
   |                 ^^^

我是Haskell的新手,所以我没有掌握它的语法,所以提前感谢你的帮助。

1 个答案:

答案 0 :(得分:1)

这里有很多错误,你应该花更多的时间阅读一些教程(learn you a HaskellReal World Haskell)。你虽然非常接近,所以我会尝试在这里做出决定。

do很特别 - 它不会将Haskell切换到&#34;命令式模式&#34;,它可以让你在使用Monads时编写更清晰的代码 - 如果你还不知道什么Monads,远离do!像return这样的关键字也不像命令式语言那样表现。尝试以一种全新的心态接近Haskell。

同样在Haskell中,缩进很重要 - 请参阅this link以获得一个很好的解释。从本质上讲,你希望所有的行都在同一个&#34;块&#34;有相同的缩进。

好的,让我们删除doreturn个关键字,并对齐缩进。我们还将参数命名为函数str - 在原始代码中,您错过了这一点。

toWordList :: String -> [String]
toWordList str =
    [toLower x | x <- str]
    let var = removePunctuation(x)
    words var

let的语法是let __ = __ in __。使用do时有不同的表示法,但暂时忘记了这一点。我们也没有说明列表理解的结果,所以让我们这样做:

toWordList str =
    let lowered = [toLower x | x <- str] in
    let var = removePunctuation lowered in
    words var

这有效!我们只需要正确地获得一些语法并避免使用do / return的一元语法糖。

虽然可以(并且很容易)使其更好。那些let块有点难看,我们可以将它们剥离。我们也可以用map toLower替换列表理解,这更加优雅,相当于你的理解:

toWordList str = words (removePunctuation (map toLower str))

很好,现在只有一行了!但是所有这些括号也是一个眼睛,我们如何使用the $ function

toWordList str = words $ removePunctuation $ map toLower str

看起来不错。我们可以做出另一项改进,即将其转换为point-free style,我们不会明确命名我们的参数 - 而是将此函数表示为其他函数的组合。

toWordList = words . removePunctuation . (map toLower)

我们已经完成了!希望前两个代码片段能够更清楚地了解Haskell语法的工作原理,最后几个可能会向您展示一些很好的例子,说明如何使相当冗长的代码更清晰。