我正在编写一个小程序,它从另一个字符串“构建”一个字符串(这是“输入字符串”(参数))。但是我得到一个解析错误(输入'=')。我怀疑我的防守表达方式有问题吗?
checkCons :: Char -> Bool
checkCons x = notElem x ['a','e','i','o','u','y']
rovarSprak :: [Char] -> [Char] -> [Char]
rovarSprak [] res = res
rovarSprak (c:restOfStr) res
| (checkCons c) == True = rovarSprak restOfStr (c:'o':c:res)
| otherwise = rovarSprak restOfStr (c:res)
如果我拨打电话:rovarSprak "abc" []
。我期待"abobcoc"
。
观察checkCons
功能是否正常工作。
答案 0 :(得分:1)
我认为您的旧代码没有正确缩进。如果我运行ghc
编译器:
rovarSprak :: [Char] -> [Char] -> [Char]
rovarSprak [] res = res
rovarSprak (c:restOfStr) res
| (checkCons c) == True = rovarSprak restOfStr (c:'o':c:res)
| otherwise = rovarSprak restOfStr (c:res)
它出错了:
strep.hs:8:1: parse error on input ‘|’
将其重写为:
rovarSprak :: [Char] -> [Char] -> [Char]
rovarSprak [] res = res
rovarSprak (c:restOfStr) res
| (checkCons c) == True = rovarSprak restOfStr (c:'o':c:res)
| otherwise = rovarSprak restOfStr (c:res)
解决了编译错误。
此外,如果尝试重现它,结果是:
"cocboba"
警卫工作正常,你的代码唯一的问题是在递归调用中:
rovarSprak restOfStr (c:'o':c:res)
-- ^push in front
你将结果推到新列表的前面,而你可能希望它在尾部。
您可以通过不使用累加器来解决此问题,但可以立即发出元素。例如:
rovarSprak :: [Char] -> [Char] rovarSprak [] = [] rovarSprak (c:restOfStr) |(checkCons c) == True= c : 'o' : c : (rovarSprak restOfStr) | otherwise = c : rovarSprak restOfStr
(以粗体和笔划冗余代码元素发射)。这也允许生成惰性列表:也许您只对输出的前三个元素感兴趣,或者输入可能是无限列表。
我建议的最后一个优化是交换两行rovarSprak
:
rovarSprak :: [Char] -> [Char] rovarSprak (c:restOfStr) | checkCons c = c : 'o' : c : (rovarSprak restOfStr) | otherwise = c : rovarSprak restOfStr rovarSprak [] = []
这是因为你更有可能在第一行匹配:对于长度为 N 的列表,第一个模式上会有 N 个调用在第二个模式上一个。