需要制作一个程序来检查给定的字符串是否是回文,它是否可以区分大小写,并且只能使用Data.char和常规函数中的ord和chr函数来忽略非字母数字字符,没有其他的。我能够创建常规的回文检查器:
reverseStr::String->String
reverStr s | s == [] = []
reverseStr (h:t) = reverseStr t ++ [h]
isPalindrome :: String -> Bool
isPalindrome s = s == reverseStr s
我已经开始研究用于规范大小写的函数:
normalizeCase::String->String
normalizeCase h | h == [] = []
normalizeCase (h) = if ord h > 64 && ord h < 123
then map (chr $ (ord h + 32)) [h]
else h
但是我得到这些错误:
• Couldn't match expected type ‘Char -> Char’
with actual type ‘Char’
• In the first argument of ‘map’, namely ‘(chr $ (ord h + 32))’
In the expression: map (chr $ (ord h + 32)) [h]
In the expression:
if ord h > 64 && ord h < 123 then
map (chr $ (ord h + 32)) [h]
else
h
|
6 | then map (chr $ (ord h + 32)) [h] | ^^^^^^^^^^^^^^^^^^
• Couldn't match type ‘Char’ with ‘[Char]’
Expected type: String
Actual type: Char
• In the expression: h
In the expression:
if ord h > 64 && ord h < 123 then
map (chr $ (ord h + 32)) [h]
else
h
In an equation for ‘normalizeCase’:
normalizeCase [h]
= if ord h > 64 && ord h < 123 then
map (chr $ (ord h + 32)) [h]
else
h
|
7 | else h | ^
我对Haskell还是很陌生,不知道如何正确实施ord或chr以便它可以与此检查器一起使用,因此将不胜感激!
答案 0 :(得分:3)
在此代码中:
normalizeCase::String->String
normalizeCase h | h == [] = []
normalizeCase (h) = if ord h > 64 && ord h < 123
then map (chr $ (ord h + 32)) [h]
else h
您的第二个模式(h)
(仅相当于h
)与 any 列表匹配(只要第一个模式{{1}尚未与之匹配) });因此h | h == []
是这里的列表,h
毫无意义,因为ord h
期望ord
,而不是Char
。
假设[Char]
是一个字符,那么h
也将是一个字符,但是chr $ ord h + 32
期望 function 作为其第一个参数;这是预期map
但您给了Char -> Char
的错误的根源。对于Char
的第二个参数,您传递map
,它是单个元素[h]
的列表(在您的代码中也是一个列表,因此您要提供{{1} }(如果需要h
)。
还假设[[Char]]
是一个字符,则您的条件[Char]
匹配大写 h
和小写 {{1 }},包括一些不需要的字符(ord h > 64 && ord h < 123
)。 A
是字符的列表的事实是发生z
但您给了[]^_`
的错误的原因。
您似乎也将递归样式与h
混合在一起–在这种情况下,您应该 使用Char
或根据情况定义函数
在此情况下,修正了这些错误后,您的代码将如何显示。首先,使用递归:
[Char]
或者,使用map
:
map
normalizeCase :: String -> String
-- Given an empty list, return an empty list.
-- This happens if the original input was empty,
-- or when we reach the end of the recursion.
normalizeCase [] = []
-- Given a non-empty list,
-- test the first character ‘c’.
normalizeCase (c : cs) = if c >= 'A' && c <= 'Z'
-- If it’s uppercase, lowercase it and
-- prepend it to the result of normalizing
-- the remainder of the string ‘cs’.
then chr (ord c + 32) : normalizeCase cs
-- Otherwise, don’t change it, but still
-- prepend it to the result of normalizing
-- the remainder of the string ‘cs’.
else c : normalizeCase cs
可以直接进行比较(map
),这样更易读,但是如果希望您也使用normalizeCase :: String -> String
-- Given any string:
normalizeCase s
-- For each character:
= map
-- If it’s uppercase, lowercase it.
(\ c -> if c >= 'A' && c <= 'Z'
then chr (ord c + 32)
else c)
-- Over the whole string.
s
进行比较,则为{{1 }}。
我知道您不应为此任务使用任何其他标准功能,但是为了将来参考,也可以使用Char
中的c >= 'A'
非常简单地实现此功能:
ord
对于删除非字母数字字符的附加任务,可以使用ord c >= 65
(带有保护条件的列表理解),或自己编写直接递归版本。