Search code examples
regexhaskellapplicativeparser-combinators

Text.Regex.Applicative - Multiline Comments


I can't figure out the correct way to use the Haskell regex-applicative package to perform a replacement on multiline comments using the replace function. First, I'm trying to get match to return the correct string as a test:

regex = pure (++) <$> string "/*" <*> many (anySym) <*> string "*/"
match regex "/* hello world */"

Which returns hello world */. I don't understand why the first matching section is cut off. Any ideas?


Solution

  • You are mixing up the applicative idioms. It's either

    f <$> x <*> y <*> z
      ^^^
    

    or

    pure f <*> x <*> y <*> z
           ^^^
    

    The mixture you have chosen

    pure f <$> x <*> y <*> z
    

    is misleading. Because

    (<$>) :: (Functor f) => (a -> b) -> f a -> f b
    

    takes a function as its left argument, pure f is being interpreted in the (->) r applicative, in which pure = const. So you get

    const (++) <$> string "/*" <*> many anySym <*> string "/*"
    

    and now we can hopefully see why the first string is ignored.

    You can't apply (++) to three arguments, which is why the other forms don't compile. What you really need, I think, is

    sequenceA :: (Applicative f) => [f a] -> f [a]
    

    which turns a list* of parsers in to a parser that gives a list, and then concat the result.

    regex = concat <$> sequenceA [string "/*", many anySym, string "*/"]
    

    *Actually sequenceA is more general, having type (Applicative f, Traversable t) => t (f a) -> f (t a), but I didn't want to get too far in the clouds for this answer.