4 ms·
OTOH, I feel it's taken too far in the regex packages. They feel extremely daunting for someone just getting started with Haskell. E.g. the wiki says that Text.
by unhammer 9y ago
OTOH, I feel it's taken too far in the regex packages. They feel extremely daunting for someone just getting started with Haskell. E.g. the wiki says that Text.Regex.TDFA is the thing to use. First try:
λ> "abc" =~ "(a|b).*"
<interactive>:1558:1-18:
Non type-variable argument
in the constraint: RegexContext
Text.Regex.TDFA.Regex source1 target
(Use FlexibleContexts to permit this)
When checking that ‘it’ has the inferred type
it :: forall source1 target.
(Data.String.IsString source1,
RegexContext Text.Regex.TDFA.Regex source1 target) =>
target
<interactive>:1558:7-8:
Could not deduce (RegexMaker
Text.Regex.TDFA.Regex CompOption ExecOption source0)
arising from a use of ‘=~’
from the context (Data.String.IsString source1,
RegexContext Text.Regex.TDFA.Regex source1 target)
bound by the inferred type of
it :: (Data.String.IsString source1,
RegexContext Text.Regex.TDFA.Regex source1 target) =>
target
at <interactive>:1558:1-18
The type variable ‘source0’ is ambiguous
Note: there are several potential instances:
instance RegexMaker
Text.Regex.TDFA.Regex
CompOption
ExecOption
Data.ByteString.Internal.ByteString
-- Defined in ‘Text.Regex.TDFA.ByteString’
instance RegexMaker
Text.Regex.TDFA.Regex
CompOption
ExecOption
Data.ByteString.Lazy.Internal.ByteString
-- Defined in ‘Text.Regex.TDFA.ByteString.Lazy’
instance RegexMaker
Text.Regex.TDFA.Regex
CompOption
ExecOption
(Data.Sequence.Seq Char)
-- Defined in ‘Text.Regex.TDFA.Sequence’
...plus one other
In the expression: "abc" =~ "(a|b).*"
In an equation for ‘it’: it = "abc" =~ "(a|b).*"
<interactive>:1558:10-18:
Could not deduce (Data.String.IsString source0)
arising from the literal ‘"(a|b).*"’
from the context (Data.String.IsString source1,
RegexContext Text.Regex.TDFA.Regex source1 target)
bound by the inferred type of
it :: (Data.String.IsString source1,
RegexContext Text.Regex.TDFA.Regex source1 target) =>
target
at <interactive>:1558:1-18
The type variable ‘source0’ is ambiguous
Note: there are several potential instances:
instance Data.String.IsString
aeson-1.2.1.0:Data.Aeson.Types.Internal.Value
-- Defined in ‘aeson-1.2.1.0:Data.Aeson.Types.Internal’
instance Data.String.IsString
Data.ByteString.Builder.Internal.Builder
-- Defined in ‘Data.ByteString.Builder’
instance Data.String.IsString Data.ByteString.Internal.ByteString
-- Defined in ‘Data.ByteString.Internal’
...plus 9 others
In the second argument of ‘(=~)’, namely ‘"(a|b).*"’
In the expression: "abc" =~ "(a|b).*"
In an equation for ‘it’: it = "abc" =~ "(a|b).*"
Scary. Next most promising hit on ddg is bos' tutorial at http://www.serpentine.com/blog/2007/02/27/a-haskell-regular-expression-tutorial/ http://www.serpentine.com/blog/2007/02/27/a-haskell-regular-... which says I should be able to get a list of results by specifying the context [String]:
λ> "abc" =~ "(a|b).*" :: [String]
<interactive>:1497:1-5:
No instance for (Data.String.IsString source10)
arising from the literal ‘"abc"’
The type variable ‘source10’ is ambiguous
Note: there are several potential instances:
instance Data.String.IsString
aeson-1.2.1.0:Data.Aeson.Types.Internal.Value
-- Defined in ‘aeson-1.2.1.0:Data.Aeson.Types.Internal’
instance Data.String.IsString
Data.ByteString.Builder.Internal.Builder
-- Defined in ‘Data.ByteString.Builder’
instance Data.String.IsString Data.ByteString.Internal.ByteString
-- Defined in ‘Data.ByteString.Internal’
...plus 7 others
In the first argument of ‘(=~)’, namely ‘"abc"’
In the expression: "abc" =~ "(a|b).*" :: [String]
In an equation for ‘it’: it = "abc" =~ "(a|b).*" :: [String]
<interactive>:1497:7-8:
No instance for (RegexContext
Text.Regex.TDFA.Regex source10 [String])
arising from a use of ‘=~’
The type variable ‘source10’ is ambiguous
Note: there is a potential instance available:
instance RegexLike a b => RegexContext a b [[b]]
-- Defined in ‘regex-base-0.93.2:Text.Regex.Base.Context’
In the expression: "abc" =~ "(a|b).*" :: [String]
In an equation for ‘it’: it = "abc" =~ "(a|b).*" :: [String]
<interactive>:1497:10-18:
No instance for (Data.String.IsString source0)
arising from the literal ‘"(a|b).*"’
The type variable ‘source0’ is ambiguous
Note: there are several potential instances:
instance Data.String.IsString
aeson-1.2.1.0:Data.Aeson.Types.Internal.Value
-- Defined in ‘aeson-1.2.1.0:Data.Aeson.Types.Internal’
instance Data.String.IsString
Data.ByteString.Builder.Internal.Builder
-- Defined in ‘Data.ByteString.Builder’
instance Data.String.IsString Data.ByteString.Internal.ByteString
-- Defined in ‘Data.ByteString.Internal’
...plus 7 others
In the second argument of ‘(=~)’, namely ‘"(a|b).*"’
In the expression: "abc" =~ "(a|b).*" :: [String]
In an equation for ‘it’: it = "abc" =~ "(a|b).*" :: [String]
… so something about overloaded strings is confusing the type checker probably. Since I'm not a complete newbie I know I can specify string types explicitly:
λ> ("abc"::String) =~ ("(a|b).*"::String) :: [String]
<interactive>:1504:17-18:
No instance for (RegexContext
Text.Regex.TDFA.Regex String [String])
arising from a use of ‘=~’
In the expression:
("abc" :: String) =~ ("(a|b).*" :: String) :: [String]
In an equation for ‘it’:
it = ("abc" :: String) =~ ("(a|b).*" :: String) :: [String]
That's … shorter, but still daunting. If I'm a bit more experienced, I know that I "just" have to do
λ> :i RegexContext
class RegexLike regex source =>
RegexContext regex source target where
match :: regex -> source -> target
matchM :: Monad m => regex -> source -> m target
-- Defined in ‘regex-base-0.93.2:Text.Regex.Base.RegexLike’
instance RegexContext Text.Regex.TDFA.Regex String String
-- Defined in ‘Text.Regex.TDFA.String’
instance RegexContext Text.Regex.Regex String String
-- Defined in ‘Text.Regex.Posix.String’
instance RegexLike a b => RegexContext a b [[b]]
-- Defined in ‘regex-base-0.93.2:Text.Regex.Base.Context’
instance RegexLike a b => RegexContext a b (MatchResult b)
-- Defined in ‘regex-base-0.93.2:Text.Regex.Base.Context’
instance RegexLike a b => RegexContext a b Int
-- Defined in ‘regex-base-0.93.2:Text.Regex.Base.Context’
instance RegexLike a b => RegexContext a b Bool
-- Defined in ‘regex-base-0.93.2:Text.Regex.Base.Context’
instance RegexLike a b =>
RegexContext
a b (AllTextSubmatches [] (b, (MatchOffset, MatchLength)))
-- Defined in ‘regex-base-0.93.2:Text.Regex.Base.Context’
instance RegexLike a b => RegexContext a b (AllTextSubmatches [] b)
-- Defined in ‘regex-base-0.93.2:Text.Regex.Base.Context’
instance RegexLike a b => RegexContext a b (AllTextMatches [] b)
-- Defined in ‘regex-base-0.93.2:Text.Regex.Base.Context’
instance RegexLike a b =>
RegexContext a b (AllSubmatches [] (MatchOffset, MatchLength))
-- Defined in ‘regex-base-0.93.2:Text.Regex.Base.Context’
instance RegexLike a b =>
RegexContext a b (AllMatches [] (MatchOffset, MatchLength))
-- Defined in ‘regex-base-0.93.2:Text.Regex.Base.Context’
instance RegexLike a b => RegexContext a b (b, b, b, [b])
-- Defined in ‘regex-base-0.93.2:Text.Regex.Base.Context’
instance RegexLike a b => RegexContext a b (b, b, b)
-- Defined in ‘regex-base-0.93.2:Text.Regex.Base.Context’
instance RegexLike a b =>
RegexContext a b (MatchOffset, MatchLength)
-- Defined in ‘regex-base-0.93.2:Text.Regex.Base.Context’
instance RegexLike a b => RegexContext a b ()
-- Defined in ‘regex-base-0.93.2:Text.Regex.Base.Context’
and somewhere in that long list of instances I see that although [String] is not an instance, [[String]] is, so finally I see I can do
λ> ("abc"::String) =~ ("(a|b).*"::String) :: [[String]]
[ [ "abc" , "a" ] ]
Of course, the end result looks nice in the code, but it takes forever to discover the API when you're new to the system (and the docs have next to no examples).
- marcosdumay 9y agoIt is daunting and those errors are very hard to follow even after you have some experience with them. That said, there's a component of "you are using it wrong" on your problem. On the middle of some code, when your data is already in well typed variables, you just write: if text =~ "(a|b).*" then trueVal else falseVal and it just works. It doesn't even matter if text is a String, Text, ByteString, or whatever. Also you just write: putStr . concat $ text =~ "(a|b).* and again, it just works. It does not matter that this is a completely different usage.
- tikhonj 9y agoMost Haskellers I know think that library is too complicated—it's trying too hard to make Haskell look like Perl. I haven't seen it used in serious code and I never use it myself; chances are, if I want to parse anything even remotely complicated, a library like Parsec is a better bet.