我正在尝试编写一个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的新手,所以我没有掌握它的语法,所以提前感谢你的帮助。
答案 0 :(得分:1)
这里有很多错误,你应该花更多的时间阅读一些教程(learn you a Haskell,Real World Haskell)。你虽然非常接近,所以我会尝试在这里做出决定。
do
很特别 - 它不会将Haskell切换到&#34;命令式模式&#34;,它可以让你在使用Monads时编写更清晰的代码 - 如果你还不知道什么Monads,远离do
!像return
这样的关键字也不像命令式语言那样表现。尝试以一种全新的心态接近Haskell。
同样在Haskell中,缩进很重要 - 请参阅this link以获得一个很好的解释。从本质上讲,你希望所有的行都在同一个&#34;块&#34;有相同的缩进。
好的,让我们删除do
和return
个关键字,并对齐缩进。我们还将参数命名为函数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语法的工作原理,最后几个可能会向您展示一些很好的例子,说明如何使相当冗长的代码更清晰。