我需要使用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 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Will Ness.. 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),而与模式匹配[_]
为O(1)。
当然,由于其他两个子句也执行O(n)运算(last
和init
),所以此特定代码仍然非常低效。一个O(n)的算法存在。
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),而与模式匹配[_]
为O(1)。
当然,由于其他两个子句也执行O(n)运算(last
和init
),所以此特定代码仍然非常低效。一个O(n)的算法存在。