如何使用正则表达式将整数与Haskell匹配?

时间:2017-12-23 21:08:59

标签: regex haskell

如何使用任何与正则表达式相关的Haskell库从123 :: Integer这样的字符串中检索123_值?

import Text.Regex.Posix

let (_,_,_,[sectionKey]) = ("123_") =~ ("(\\d+)_" :: String) :: (String, String, String, [Int])

我已尝试过上述(使用https://hackage.haskell.org/package/regex-posix库)产生错误:

• No instance for (RegexContext
                     Regex [Char] (String, String, String, [Int]))
    arising from a use of ‘=~’
• In the expression:
      ("123_") =~ ("(\\d+)_" :: String) ::
        (String, String, String, [Int])
  In a pattern binding:
    (_, _, _, [sectionKey])
      = ("123_") =~ ("(\\d+)_" :: String) ::
          (String, String, String, [Int])

这是一个简化的案例,我正在寻找一种能够提供正则表达式兼容解决方案的解决方案。

1 个答案:

答案 0 :(得分:7)

首先,我不会使用正则表达式库 - 因为now you got two problems,haskell有一个很好的 - 没有伟大的解析器生态系统可以为你完成这项工作。

你的问题的解决方案是 - 我认为你使用了错误的正则表达式。

$ stack ghci --package regex-posix --package safe
...
Prelude> :m + Safe Text.Regex.Posix
Prelude Safe Text.Regex.Posix> readMay ("123_" =~ "[0-9]+") :: Maybe Integer
Just 123

使用正则表达式的缺点是它们首先难以理解/正确,并且在事后保持,容易出错(在我看来) - 而且。当您与之匹配时,您将获得匹配的String。即("123_" =~ "([0-9]+)_") :: String将产生“123_”而非“123”,因此“readMay ...”将返回Nothing而不是Just 123

因此我建议使用解析库 - 类似attoparsec。但正如我所说,如果你不喜欢这个,你会有很多解析选择。

$ stack ghci --package attoparsec
Prelude> :set -XOverloadedStrings
Prelude> import Data.Attoparsec.ByteString.Char8 as C8
Prelude Data.Attoparsec.Char8> :{
Prelude Data.Attoparsec.Char8| strangeNumber = do
Prelude Data.Attoparsec.Char8|   d <- decimal
Prelude Data.Attoparsec.Char8|   char '_'
Prelude Data.Attoparsec.Char8|   return d
Prelude Data.Attoparsec.Char8| :}
Prelude C8> parseOnly strangeNumber "123_" :: Either String Integer
Right 123

将它放在ghci中有点笨拙,但在文件中它非常精细且可维护 - 所以如果你想在数字的开头和/或结尾允许可选的'_',你可以把它写成< / p>

StrangeNumber.hs

strangeNumber :: Parser Integer
strangeNumber = do
  skipMany (char '_')
  d <- decimal
  skipMany (char '_')
  return d

并在GHCi中使用它

Prelude Data.Attoparsec.ByteString.Char8> parseOnly strangeNumber "123_"
Right 123
Prelude Data.Attoparsec.ByteString.Char8> parseOnly strangeNumber "_123_"
Right 123
Prelude Data.Attoparsec.ByteString.Char8> parseOnly strangeNumber "_123__"
Right 123
相关问题