Haskell 尽管有明确的 Bool 类型注释,正则表达式上下文不明确类型在 ghci 中成功

Haskell regex context ambiguous type despite explicit Bool type annotation, succeeds in ghci

这适用于解释器会话

λ> 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

这太棒了,正好满足了我的需要。

但是,相同的代码无法在脚本中编译:

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.

我在末尾有一个明确的 :: Bool 上下文来准确提供此信息。为什么这会在 ghci 中成功,但在编译时无法捕获相同的指令,我该如何解决?

歧义不在于 x =~ "csv$" 的类型是什么 - 这已经从您对 filter 的使用中确定了。问题是 "csv$" 文字本身。根据错误消息,您启用了 OverloadedStrings 语言扩展。这里的歧义在于弄清楚 "csv$" 需要是哪种类型的字符串。

您的解决方案是

  • 关闭OverloadedStrings(如果您不需要此模块),或
  • "csv$" 添加类型注释,因此您有 \x -> x =~ ("csv$" :: String) 而不是 \x -> x =~ "csv$" :: Bool

如果这是一个经常出现的问题,您可能需要尝试使用 ExtendedDefaultRules 并在您的文件中包含一个 default 声明。

这在 GHCi 中成功的原因可能是因为您没有在那里启用 OverloadedStrings(或者可能是由于 GHCi 的不同默认规则)。