“=〜”raise“没有实例(RegexContext Regex [Char] [String])”

时间:2011-10-03 14:33:04

标签: regex haskell

操作系统:MacOSX 10.7.1 来自brew的GHC和Haskell平台。

   GHCi, version 7.0.4: http://www.haskell.org/ghc/  :? for help
    Loading package ghc-prim ... linking ... done.
    Loading package integer-gmp ... linking ... done.
    Loading package base ... linking ... done.
    Loading package ffi-1.0 ... linking ... done.
    Prelude> :m +Text.Regex.Posix
    Prelude Text.Regex.Posix> "foo" =~ "o" :: [String]

    <interactive>:1:7:
        No instance for (RegexContext Regex [Char] [String])
          arising from a use of `=~'
        Possible fix:
          add an instance declaration for
          (RegexContext Regex [Char] [String])
        In the expression: "foo" =~ "o" :: [String]
        In an equation for `it': it = "foo" =~ "o" :: [String]
    Prelude Text.Regex.Posix> "foo" =~ "o" :: String
    Loading package array-0.3.0.2 ... linking ... done.
    Loading package bytestring-0.9.1.10 ... linking ... done.
    Loading package containers-0.4.0.0 ... linking ... done.
    Loading package transformers-0.2.2.0 ... linking ... done.
    Loading package mtl-2.0.1.0 ... linking ... done.
    Loading package regex-base-0.93.2 ... linking ... done.
    Loading package regex-posix-0.95.1 ... linking ... done.
    "o"

我相信库已更新。我认为"foo" =~ "o" :: [String]的输出是["o", "o"]

任何建议都会受到赞赏。

4 个答案:

答案 0 :(得分:11)

ghci> getAllTextMatches ("foo" =~ "o" :: AllTextMatches [] String)
["o", "o"]

我没有在Haskell中使用正则表达式(我认为Dan Burton's answer更加惯用)。

所以我想出来的方式是我查看了你的类型错误No instance for (RegexContext Regex [Char] [String]),并弹出了ghci:

ghci> :t (=~)
(=~)
  :: (RegexMaker Regex CompOption ExecOption source,
      RegexContext Regex source1 target) =>
     source1 -> source -> target

所以RegexContext Regex [Char] [String]是一个包含返回类型"foo" =~ "o" :: [String]的类。所以我看看这个类的实例确实存在,所以我可以找出允许返回值的内容:

ghci> :i RegexContext
class RegexLike
        regex source => RegexContext regex source target where
  match :: regex -> source -> target
  matchM :: Monad m => regex -> source -> m target
        -- Defined in Text.Regex.Base.RegexLike
instance RegexContext Regex String String
  -- Defined in Text.Regex.Posix.String
instance RegexLike a b => RegexContext a b [[b]]
  -- Defined in Text.Regex.Base.Context
...
instance RegexLike a b => RegexContext a b (AllTextMatches [] b)
  -- Defined in Text.Regex.Base.Context
...

AllTextMatches名称似乎表明您在寻找什么,所以我检查了一下:

ghci> :i AllTextMatches
newtype AllTextMatches f b
  = AllTextMatches {getAllTextMatches :: f b}
        -- Defined in Text.Regex.Base.RegexLike
instance RegexLike a b => RegexContext a b (AllTextMatches [] b)
  -- Defined in Text.Regex.Base.Context

所以这是用于提取所有文本匹配的类型,正如我怀疑的那样。我需要做的就是表明我想要一个这种类型的返回值。

还注意[[b]]的可能返回类型,我假设它返回包含每个完整匹配及其所有子匹配的列表列表:

ghci> "foo" =~ "o" :: [[String]]
[["o"],["o"]]
ghci> "foo bar baz" =~ "[aeiou](.)" :: [[String]]
[["oo","o"],["ar","r"],["az","z"]]

所以也许这是你打算使用的类型,而不是[String]。当[String]存在时,我可以看到[[String]]略微含糊不清 - "foo bar baz" =~ "[aeiou](.)" :: [String]fst ("foo bar baz" =~ "[aeiou](.)" :: [[String]])map fst ("foo bar baz" =~ "[aeiou](.)" :: [[String]])

答案 1 :(得分:9)

这也有效

ghci> getAllTextMatches $ "foo" =~ "o" :: [String]
["o","o"]

答案 2 :(得分:3)

试试这个:

Prelude Text.Regex.Posix> getAllTextMatches ("foo" =~ "o" :: AllTextMatches [] String)
["o","o"]

答案 3 :(得分:2)

另一种可能的解决方案是:

map head $ "foo" =~ "o" :: [String]

说明

(=~)的结果绑定到[[String]]将产生匹配列表,其中每个匹配由字符串列表表示。在每个列表中,其head将是整个匹配,并且tail匹配每个子匹配:

> "foo goo bar" =~ "(.)o(.)" :: [[String]]
[["foo","f","o"],["goo","g","o"]]

-- Get the second submatch (2) of the first match (0)
> "foo goo bar" =~ "(.)o(.)" !! 0 !! 2 :: String
"o"

-- Get the first submatch (1) of the second match (1)
> "foo goo bar" =~ "(.)o(.)" !! 1 !! 1 :: String
"g"

简而言之,map head $ string =~ regexp :: [String]包含regexpstring的完整匹配。 map tail $ string =~ regexp :: [[String]]包含子匹配,在原始正则表达式中通过括起括号()来表示。