忽略非字母数字字符和大小写Haskell的回文检查器

时间:2018-12-18 00:38:16

标签: haskell functional-programming palindrome

需要制作一个程序来检查给定的字符串是否是回文,它是否可以区分大小写,并且只能使用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以便它可以与此检查器一起使用,因此将不胜感激!

1 个答案:

答案 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(带有保护条件的列表理解),或自己编写直接递归版本。