Haskell使用PCRE库验证邮箱时遇正则解析错误求助
使用pcre-heavy库验证邮箱时的GHC解析错误
问题概述
在GHC 9.12.2版本中,使用pcre-heavy库的模板语法编写邮箱验证正则时,触发解析错误:parse error on input ‘2’,错误定位到正则表达式的{2,64}部分。
相关代码
import ClassyPrelude import Domain.Validation import Text.Regex.PCRE.Heavy import Control.Monad.Except type Validation e a = a -> Maybe e validate :: (a -> b) -> [Validation e a] -> a -> Either [e] b validate constructor validations val = case concatMap (\f -> maybeToList $ f val) validations of [] -> Right $ constructor val errs -> Left errs newtype Email = Email { emailRaw :: Text } deriving (Show, Eq, Ord) rawEmail :: Email -> Text rawEmail = emailRaw mkEmail :: Text -> Either [Text] Email mkEmail = validate Email [ regexMatches [re|^[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,64}$|] "Not a valid email" ]
Cabal配置
default-extensions: TemplateHaskell , ConstraintKinds , FlexibleContexts , NoImplicitPrelude , OverloadedStrings , TemplateHaskell build-depends: base ^>=4.21.0.0 , katip >= 0.8.8.2 , string-random == 0.1.4.4 , mtl , data-has , classy-prelude , pcre-heavy , time , time-lens hs-source-dirs: src default-language: GHC2024
错误日志
cabal build Resolving dependencies... Build profile: -w ghc-9.12.2 -O1 In order, the following will be built (use -v for more details): - practical-web-dev-ghc-0.1.0.0 (lib) (first run) - practical-web-dev-ghc-0.1.0.0 (exe:practical-web-dev-ghc) (first run) Configuring library for practical-web-dev-ghc-0.1.0.0... Preprocessing library for practical-web-dev-ghc-0.1.0.0... Building library for practical-web-dev-ghc-0.1.0.0... [1 of 5] Compiling Domain.Validation ( src/Domain/Validation.hs, dist-newstyle/build/aarch64-osx/ghc-9.12.2/practical-web-dev-ghc-0.1.0.0/build/Domain/Validation.o, dist-newstyle/build/aarch64-osx/ghc-9.12.2/practical-web-dev-ghc-0.1.0.0/build/Domain/Validation.dyn_o ) [2 of 5] Compiling Domain.Auth ( src/Domain/Auth.hs, dist-newstyle/build/aarch64-osx/ghc-9.12.2/practical-web-dev-ghc-0.1.0.0/build/Domain/Auth.o, dist-newstyle/build/aarch64-osx/ghc-9.12.2/practical-web-dev-ghc-0.1.0.0/build/Domain/Auth.dyn_o ) src/Domain/Auth.hs:42:57: error: [GHC-58481] parse error on input ‘2’ | 42 | [re|^[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,64}$|] | ^ [4 of 5] Compiling Logger ( src/Logger.hs, dist-newstyle/build/aarch64-osx/ghc-9.12.2/practical-web-dev-ghc-0.1.0.0/build/Logger.o, dist-newstyle/build/aarch64-osx/ghc-9.12.2/practical-web-dev-ghc-0.1.0.0/build/Logger.dyn_o ) [5 of 5] Compiling MyLib ( src/MyLib.hs, dist-newstyle/build/aarch64-osx/ghc-9.12.2/practical-web-dev-ghc-0.1.0.0/build/MyLib.o, dist-newstyle/build/aarch64-osx/ghc-9.12.2/practical-web-dev-ghc-0.1.0.0/build/MyLib.dyn_o ) Error: [Cabal-7125] Failed to build practical-web-dev-ghc-0.1.0.0 (which is required by exe:practical-web-dev-ghc from practical-web-dev-ghc-0.1.0.0).
原因分析
pcre-heavy的[re|...]是基于TemplateHaskell的语法糖,它默认将模板中的逗号视为参数分隔符。正则表达式里的{2,64}包含逗号,导致GHC错误地将2解析为模板的第二个输入参数,从而触发语法错误。
解决办法
方法1:转义正则中的逗号
在正则的逗号前添加反斜杠,让TemplateHaskell识别它为正则的一部分而非参数分隔符:
mkEmail :: Text -> Either [Text] Email mkEmail = validate Email [ regexMatches [re|^[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2\,64}$|] "Not a valid email" ]
方法2:直接使用字符串编译正则
避开模板语法,用pcre-heavy提供的compile函数从字符串编译正则表达式,这样无需处理逗号转义:
mkEmail :: Text -> Either [Text] Email mkEmail = validate Email [ regexMatches (compile "^[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}$") "Not a valid email" ]
注意:Haskell字符串中的反斜杠需要双重转义,因此正则里的\.要写成\\.。
内容的提问来源于stack exchange,提问作者user51
相关产品推荐
相关产品推荐

