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?
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.