Reputation: 6936
I'm struggling to understand this type signature:
Prelude Text.Regex.Posix> :t (=~)
(=~)
:: (Text.Regex.Base.RegexLike.RegexMaker
Regex CompOption ExecOption source,
Text.Regex.Base.RegexLike.RegexContext Regex source1 target) =>
source1 -> source -> target
I reckon they list type classes, source
, source1
and target
should be instances of, but the semantics look completely arcane (that is, I would not be able to replicate it, even if I understood what it says).
Upvotes: 4
Views: 715
Reputation: 204678
I wrote a fairly thorough description of the Text.Regex typeclasses in another answer.
Copying most of that here...
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
Upvotes: 3
Reputation: 54724
There's nothing strange going on here: just some type classes with a lot of arguments. (The long Text.Regex.Base...
module names don't help, either.)
RegexMaker
instance for: Regex
, CompOption
, ExecOption
, and whatever type source
isRegexContext
instance for: Regex
, whatever type source1
is, and whatever type target
is(=~)
function itself takes a source1
and a source
and gives a target
Haskell's own (+)
operator is a similar shape to (=~)
, but its type is hopefully easier to read:
(+) :: Num a => a -> a -> a
Upvotes: 4