初学者 Haskell 问题 - 无法将类型“Bool”与“[Char]”匹配
Beginner Haskell problem - Couldn't match type ‘Bool’ with ‘[Char]’
我需要在 Haskell 中使用递归制作一个回文检查器来完成家庭作业。该函数应该接受一个字符串和 return 一个 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,如果是,return为真。如果不是,它会检查第一个字符和最后一个字符是否不同,如果不同,returns 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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
。但真正的意思是有一个布尔值,用作守卫,select 适当的行动过程。因此出现错误消息。我们已经有了 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) 算法。
我需要在 Haskell 中使用递归制作一个回文检查器来完成家庭作业。该函数应该接受一个字符串和 return 一个 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,如果是,return为真。如果不是,它会检查第一个字符和最后一个字符是否不同,如果不同,returns 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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
。但真正的意思是有一个布尔值,用作守卫,select 适当的行动过程。因此出现错误消息。我们已经有了 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) 算法。