我的警惕表情有问题吗?

Wrong in my guard expression?

我正在编写一个小程序,其中 "builds up" 一个字符串来自另一个字符串(即 "input string"(参数))。但是我收到一个解析错误(在输入“=”时)。我怀疑我的守卫表情有问题?

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 函数是否按预期运行。

我认为您的旧代码缩进不正确。如果我 运行 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 调用第一个模式,one 调用第二个模式。