在Haskell中更改字符串

时间:2017-05-11 12:32:02

标签: haskell

我有这个函数,必须检查字符串中的字符是字母,数字还是标点符号,返回True时的情况,否则为False。但如果我测试它,它就不起作用。

punct :: Char -> Bool
punct c | c `elem` ['.', ',', '?', '!', ':', ';', '(', ')'] = True 
        | c isDigit = True  
        | c isAlpha = True 
        | otherwise = False

此功能在上述其中一个之后添加一个空格。

format :: String -> String
format s = intercalate "" [if (punct c) then (c:" ") else [c] | c <- s]

之后,我需要删除上面的内容,在punct中检查。 实际上我认为我可以用空格直接替换那些来自punct的那些 我尝试过这样的事情:

format :: String -> String
format s = map (\c -> if punct c then (c:" ") else [c] )

但它没有用,有什么建议吗?我想我可以使用地图和过滤器?我错了吗?

2 个答案:

答案 0 :(得分:2)

工作的原因是因为map Char位于String上([Char] s)map。因此,[String]的输出将为punct。不过,如果你想删除上面的那些,你在地图中的功能就不会让你的角色消失。

此外,您isDigit功能错误。 isDigit c等是函数。因此,您可以使用c isDigit,而不是punct :: Char -> Bool punct c | c `elem` ['.', ',', '?', '!', ':', ';', '(', ')'] = True | isDigit c = True | isAlpha c = True | otherwise = False

来调用它
punct :: Char -> Bool
punct c = isDigit c || isDigit c || c `elem` ['.', ',', '?', '!', ':', ';', '(', ')']

尽管如此,您可以轻松地将此语句更紧凑并将其转换为:

filter

这里有两个选项:(1)你要做一个后期处理,你可以过滤掉所有的标点符号;或者(2)如果你删除标点符号,你实际上是做替换而不是插入空格。

(1)后期处理

后处理只是post_format :: String -> String post_format = filter (not . punct)

format

如果您仍想使用“原始helper功能,最好使用后期处理。

(1)替换

在这种情况下,您可以使用helper :: Char -> Char helper x | punct x = ' ' | otherwise = x 函数:

format

然后format :: String -> String format = map helper 崩溃到:

grid.arrange

答案 1 :(得分:1)

好吧,这段代码不会编译。让我们来解决为什么它不能一次编译一个问题:

首先,在punct函数中,此编译错误发生两次:

Foo.hs:7:11: error:
    • Couldn't match expected type ‘(Char -> Bool) -> Bool’
                  with actual type ‘Char’
    • The function ‘c’ is applied to one argument,
      but its type ‘Char’ has none
      In the expression: c isDigit
      In a stmt of a pattern guard for
                     an equation for ‘punct’:
        c isDigit

编译器在这里试图告诉你的是你写了“call c作为一个函数,传递参数isDigit”,显然你的意思是反过来。所以首先我们交换那些:

punct :: Char -> Bool
punct c | c `elem` ['.', ',', '?', '!', ':', ';', '(', ')'] = True 
        | isDigit c = True  
        | isAlpha c = True 
        | otherwise = False

修复后,您的第一个format函数实际编译:

format1 :: String -> String
format1 s = intercalate "" [if (punct c) then (c:" ") else [c] | c <- s]

它似乎也像宣传的那样工作:

*Foo> format1 "a.b_c"
"a . b _c "

好的,现在第二个format函数呢?好吧,起初它不会编译:

Foo.hs:18:12: error:
    • Couldn't match type ‘[Char] -> [[Char]]’ with ‘[Char]’
      Expected type: String
        Actual type: [Char] -> [[Char]]
    • Probable cause: ‘map’ is applied to too few arguments
      In the expression: map (\ c -> if punct c then (c : " ") else [c])
      In an equation for ‘format’:
          format s = map (\ c -> if punct c then (c : " ") else [c])

编译器在这里告诉你(带有“可能的原因”消息),你忘了在右侧使用s,并且应该已经写了:

format s = map (\c -> if punct c then (c:" ") else [c] ) s

但是无法编译的事件:(但现在错误信息不同)

Foo.hs:18:12: error:
    • Couldn't match type ‘[Char]’ with ‘Char’
      Expected type: String
        Actual type: [[Char]]
    • In the expression:
        map (\ c -> if punct c then (c : " ") else [c]) s
      In an equation for ‘format’:
          format s = map (\ c -> if punct c then (c : " ") else [c]) s

这就是说你的结果应该是String(即Char[Char]的列表),而是String的列表(即[[Char]]

这是因为您将每个字符转换为字符串,而不是字符。解决此问题的一种方法是将每个字符转换为字符:

format s = map (\c -> if punct c then ' ' else c ) s

另一种方法是像以前一样应用intercalate ""(或concat)将字符串列表加入到单个字符串中:

format s = intercalate "" $ map (\c -> if punct c then " " else [c] ) s