我正在尝试使用以下代码进行正则表达式替换
import Text.RE.Replace
import Text.RE.TDFA.String
onlyLetters :: String -> String
onlyLetters s = replaceAll "" $ s *=~ [re|$([^a-zA-Z])|]
我发现很难找到任何关于此的可理解的文档。 这会产生编译错误:
src\Pangram.hs:6:53: error: parse error on input `]'
|
6 | onlyLetters s = replaceAll "" $ (s *=~ [re|[a-zA-Z]|])
| ^
Progress 1/2
-- While building package pangram-2.0.0.12 (scroll up to its section to see the error) using:
C:\sr\setup-exe-cache\x86_64-windows\Cabal-simple_Z6RU0evB_3.0.1.0_ghc-8.8.4.exe --builddir=.stack-work\dist\29cc6475 build lib:pangram test:test --ghc-options " -fdiagnostics-color=always"
Process exited with code: ExitFailure 1
PS C:\Users\mcleg\Exercism\haskell\pangram> stack test
pangram> configure (lib + test)
Configuring pangram-2.0.0.12...
pangram> build (lib + test)
Preprocessing library for pangram-2.0.0.12..
Building library for pangram-2.0.0.12..
[1 of 2] Compiling Pangram
src\Pangram.hs:7:56: error: parse error on input `]'
|
7 | onlyLetters s = replaceAll "" $ s *=~ [re|$([^a-zA-Z])|]
| ^
Progress 1/2
-- While building package pangram-2.0.0.12 (scroll up to its section to see the error) using:
C:\sr\setup-exe-cache\x86_64-windows\Cabal-simple_Z6RU0evB_3.0.1.0_ghc-8.8.4.exe --builddir=.stack-work\dist\29cc6475 build lib:pangram test:test --ghc-options " -fdiagnostics-color=always"
Process exited with code: ExitFailure 1
该支架有什么问题,我该如何正确执行此操作? 谢谢 -斯凯
[…|…|]
是准引用语法[haskell-wiki]。这是 Haskell 语法的扩展,默认情况下不启用。
您可以使用
LANGUAGE
编译指示打开此功能:
{-# LANGUAGE QuasiQuotes #-}
import Text.RE.Replace
import Text.RE.TDFA.String
onlyLetters :: String -> String
onlyLetters s = replaceAll "" $ s *=~ [re|$([^a-zA-Z])|]
准引号将生成 Haskell 代码,然后在 Haskell 程序中使用。这意味着通过准引号,可以在编译时完成正则表达式的验证,与在运行时编译正则表达式相比,甚至可能稍微优化效率。
对于给定的
onlyLetters
函数,我们得到:
*Main> onlyLetters "fo0b4r"
"fobr"
Willem Van Onsem 的答案是对这个问题的更好答案,但我会建议一个 “试试这个” 回答。
这就是如何在普通 Haskell 中进行文本替换,而无需使用准引用正则表达式的复杂性。
与 https://hackage.haskell.org/package/replace-megaparsec/docs/Replace-Megaparsec.html#v:streamEdit
{-# LANGUAGE TypeFamilies #-}
import Text.Megaparsec
import Text.Megaparsec.Char
import Replace.Megaparsec
import Data.Void
-- | Invert a single-token parser “character class”.
-- | For example, match any single token except a letter or whitespace: `anySingleExcept (letterChar <|> spaceChar)`
anySingleExcept :: (MonadParsec e s m, Token s ~ Char) => m (Token s) -> m (Token s)
anySingleExcept p = notFollowedBy p *> anySingle
-- | A parser monad pattern which matches anything except letters.
nonLetters :: Parsec Void String String
nonLetters = many (anySingleExcept letterChar)
onlyLetters :: String -> String
onlyLetters = streamEdit nonLetters (const "")
onlyLetters "fo0b4r"
"fobr"