我需要使用Haskell中的递归进行回文检查,以完成作业。该函数应接收一个字符串并返回Bool
。尝试编译时,出现错误"Couldn't match type ‘Bool’ with ‘[Char]’."
我对Haskell来说还很陌生,所以我敢肯定我只是忽略了一些愚蠢的事情,但我想我仍然会寻求帮助。我在下面粘贴了我的代码以及收到的全部错误。
isPalindrome :: String -> Bool
isPalindrome s
| isPalindrome ((null s) || (length s == 1)) = True
| isPalindrome ((s !! 0) /= (s !! (length s - 1))) = False
| otherwise = isPalindrome (tail (init s))
我的实现检查输入字符串是否为空或大小为1,如果为空,则返回true。如果不是,则检查第一个字符和最后一个字符是否不同,如果不同,则返回false。否则,它将再次调用自身,并传入第一个和最后一个字符被截断的字符串。
main.hs:15:19: error:
• Couldn't match type ‘Bool’ with ‘[Char]’
Expected type: String
Actual type: Bool
• In the first argument of ‘isPalindrome’, namely
‘((null s) || (length s == 1))’
In the expression: isPalindrome ((null s) || (length s == 1))
In a stmt of a pattern guard for
an equation for ‘isPalindrome’:
isPalindrome ((null s) || (length s == 1))
|
15 | | isPalindrome ((null s) || (length s == 1)) = True
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
main.hs:16:19: error:
• Couldn't match type ‘Bool’ with ‘[Char]’
Expected type: String
Actual type: Bool
• In the first argument of ‘isPalindrome’, namely
‘((s !! 0) /= (s !! (length s - 1)))’
In the expression: isPalindrome ((s !! 0) /= (s !! (length s - 1)))
In a stmt of a pattern guard for
an equation for ‘isPalindrome’:
isPalindrome ((s !! 0) /= (s !! (length s - 1)))
|
16 | | isPalindrome ((s !! 0) /= (s !! (length s - 1))) = False
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
答案 0 :(得分:5)
f x
是带有参数f
的函数x
的函数调用。但是,如果测试表达式x
已经足够了,您就不需要调用该函数:
isPalindrome :: String -> Bool
isPalindrome s
-- f x
| {- isPalindrome -} ((null s) || (length s == 1)) -- here
= True
| {- isPalindrome -} ((s !! 0) /= (s !! (length s - 1))) -- and here
= False
| otherwise = isPalindrome (tail (init s))
isPalindrome :: String -> Bool
表示isPalindrom
的第一个参数应为String
。但是实际上是要有一个布尔值(用作保护措施)来选择适当的操作过程。因此,错误消息。我们已经有了Bool
。
最后一行中的函数调用是确实必须执行的递归调用。
{- ... -}
是Haskell中的多行注释。
Haskell惯用的,更惯用的方法是不显式执行那些测试,而是通过子句在函数定义中安排等效的模式匹配:
isPalindrome :: String -> Bool
isPalindrome [] = True -- (null s)
isPalindrome [_] = True -- (length s == 1)
isPalindrome -- [a, ..., b] | a /= b
(x:xs) | x /= last xs
= False -- ((s !! 0) /= (s !! (length s - 1)))
isPalindrome -- [a, ...xs, b]
(_:xs) = isPalindrome -- xs
(init xs)
上面的代码在注释中包含一些虚构的列表模式,在代码本身中包含与Haskell等效的列表模式。
事实上,正如@chepner在评论中指出的,模式通常可以帮助避免效率低下:计算length
为 O(n),而模式与{{ 1}}是 O(1)。
当然,由于其他两个子句也执行 O(n)操作([_]
和last
),因此该特定代码仍然非常低效。存在 O(n)算法。