case-insensitive regular expressions
case-insensitive, haskell, regex
Solution
All the `Text.Regex.*` modules make heavy use of typeclasses, which are there for extensibility and "overloading"-like behavior, but make usage less obvious from just seeing types.
Now, you've probably been started off from the basic `=~` matcher.
(=~) ::
( RegexMaker Regex CompOption ExecOption source
, RegexContext Regex source1 target )
=> source1 -> source -> target
(=~~) ::
( RegexMaker Regex CompOption ExecOption source
, RegexContext Regex source1 target, Monad m )
=> source1 -> source -> m target
To use `=~`, there must exist an instance of `RegexMaker ...` for the LHS, and `RegexContext ...` for the RHS and result.
class RegexOptions regex compOpt execOpt | ...
| regex -> compOpt execOpt
, compOpt -> regex execOpt
, execOpt -> regex compOpt
class RegexOptions regex compOpt execOpt
=> RegexMaker regex compOpt execOpt source
| regex -> compOpt execOpt
, compOpt -> regex execOpt
, execOpt -> regex compOpt
where
makeRegex :: source -> regex
makeRegexOpts :: compOpt -> execOpt -> source -> regex
A valid instance of all these classes (for example, `regex=Regex`, `compOpt=CompOption`, `execOpt=ExecOption`, and `source=String`) means it's possible to compile a `regex` with `compOpt,execOpt` options from some form `source`. (Also, given some `regex` type, there is exactly one `compOpt,execOpt` set that goes along with it. Lots of different `source` types are okay, though.)
class Extract source
class Extract source
=> RegexLike regex source
class RegexLike regex source
=> RegexContext regex source target
where
match :: regex -> source -> target
matchM :: Monad m => regex -> source -> m target
A valid instance of all these classes (for example, `regex=Regex`, `source=String`, `target=Bool`) means it's possible to match a `source` and a `regex` to yield a `target`. (Other valid `target`s given these specific `regex` and `source` are `Int`, `MatchResult String`, `MatchArray`, etc.)
Put these together and it's pretty obvious that `=~` and `=~~` are simply convenience functions
source1 =~ source
= match (makeRegex source) source1
source1 =~~ source
= matchM (makeRegex source) source1
and also that `=~` and `=~~` leave no room to pass various options to `makeRegexOpts`.
You could make your own
(=~+) ::
( RegexMaker regex compOpt execOpt source
, RegexContext regex source1 target )
=> source1 -> (source, compOpt, execOpt) -> target
source1 =~+ (source, compOpt, execOpt)
= match (makeRegexOpts compOpt execOpt source) source1
(=~~+) ::
( RegexMaker regex compOpt execOpt source
, RegexContext regex source1 target, Monad m )
=> source1 -> (source, compOpt, execOpt) -> m target
source1 =~~+ (source, compOpt, execOpt)
= matchM (makeRegexOpts compOpt execOpt source) source1
which could be used like
"string" =~+ ("regex", CompCaseless + compUTF8, execBlank) :: Bool
or overwrite `=~` and `=~~` with methods which can accept options
import Text.Regex.PCRE hiding ((=~), (=~~))
class RegexSourceLike regex source
where
makeRegexWith source :: source -> regex
instance RegexMaker regex compOpt execOpt source
=> RegexSourceLike regex source
where
makeRegexWith = makeRegex
instance RegexMaker regex compOpt execOpt source
=> RegexSourceLike regex (source, compOpt, execOpt)
where
makeRegexWith (source, compOpt, execOpt)
= makeRegexOpts compOpt execOpt source
source1 =~ source
= match (makeRegexWith source) source1
source1 =~~ source
= matchM (makeRegexWith source) source1
or you could just use `match`, `makeRegexOpts`, etc. directly where needed.
Problem
What's the best way to use regular expressions with options (flags) in Haskell I use ``` Text.Regex.PCRE ``` The documentation lists a few interesting options like compCaseless, compUTF8, ... But I don't know how to use them with (=~)