This works in an interpreter session
λ> import Text.Regex.Base
λ> import Text.Regex.Posix
λ> import Data.List (sort)
λ> import System.Directory
λ> ls <- getDirectoryContents "."
λ> let csvs = sort $ filter (\x -> x =~ "csv$" :: Bool) ls
λ> recent = last csvs
This is great and gives me exactly what I need.
However, the same code fails to compile in a script:
t10.hs:40:35-45: error: …
• Ambiguous type variable ‘source0’ arising from a use of ‘=~’
prevents the constraint ‘(RegexMaker
Regex CompOption ExecOption source0)’ from being solved.
Probable fix: use a type annotation to specify what ‘source0’ should be.
These potential instances exist:
instance RegexMaker Regex CompOption ExecOption C.ByteString
-- Defined in ‘Text.Regex.Posix.ByteString’
instance RegexMaker Regex CompOption ExecOption LB.ByteString
-- Defined in ‘Text.Regex.Posix.ByteString.Lazy’
• In the expression: x =~ "csv$" :: Bool
In the first argument of ‘filter’, namely
‘(\ x -> x =~ "csv$" :: Bool)’
In the second argument of ‘($)’, namely
‘filter (\ x -> x =~ "csv$" :: Bool) ls’
t10.hs:40:40-45: error: …
• Ambiguous type variable ‘source0’ arising from the literal ‘"csv$"’
prevents the constraint ‘(Data.String.IsString
source0)’ from being solved.
Probable fix: use a type annotation to specify what ‘source0’ should be.
I have an explicit :: Bool
context at the end to provide exactly this information. Why would this be succeeding in ghci but failing to catch this same instruction when compiling, and how can I fix it?
The ambiguity is not about what the type of x =~ "csv$"
is - that is already determined from your use of filter
. The problem is the "csv$"
literal itself. Based on the error message, you have the OverloadedStrings
language extension enabled. The ambiguity here is figuring out which type of string "csv$"
needs to be.
Your solution is to either
OverloadedStrings
(if you don't need it for this module), or"csv$"
, so you have \x -> x =~ ("csv$" :: String)
instead of \x -> x =~ "csv$" :: Bool
If this is a problem that is cropping up a lot, you may want to play with the ExtendedDefaultRules
and have a default
declaration in your file.
The reason this succeeds in GHCi is probably because because you didn't have OverloadedStrings
enabled there (or possibly due to GHCi's different defaulting rules).