我的守卫表达错了吗?

时间:2016-05-01 12:44:25

标签: haskell guard

我正在编写一个小程序,它从另一个字符串“构建”一个字符串(这是“输入字符串”(参数))。但是我得到一个解析错误(输入'=')。我怀疑我的防守表达方式有问题吗?

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功能是否正常工作。

1 个答案:

答案 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 个调用在第二个模式上一个