Como você declara um padrão regex em Haskell?
Estou tentando substituir o regex pelo seguinte código
import Text.RE.Replace
import Text.RE.TDFA.String
onlyLetters :: String -> String
onlyLetters s = replaceAll "" $ s *=~ [re|$([^a-zA-Z])|]
Achei muito difícil encontrar qualquer documentação compreensível sobre isso. Isso produz o erro de compilação:
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
Qual é o problema com esse suporte e como faria isso corretamente? Obrigado -Skye
Respostas
A sintaxe[…|…|]
é quase cotação [haskell-wiki] . Esta é uma extensão da sintaxe de Haskell e não está habilitada por padrão.
Você pode ativar isso com um LANGUAGE
pragma:
{-# LANGUAGE QuasiQuotes #-}
import Text.RE.Replace
import Text.RE.TDFA.String
onlyLetters :: String -> String
onlyLetters s = replaceAll "" $ s *=~ [re|$([^a-zA-Z])|]
Os quasiquotes irão gerar código Haskell e este é então usado no programa Haskell. Isso significa que, por meio dos quasiquotes, a validação da regex pode ser feita em tempo de compilação e pode até otimizar ligeiramente a eficiência em comparação com a compilação da regex em tempo de execução.
Para a onlyLetters
função fornecida , obtemos:
*Main> onlyLetters "fo0b4r"
"fobr"
A resposta de Willem Van Onsem é uma resposta melhor para a pergunta, mas vou sugerir uma resposta “tente isso” .
É assim que você pode fazer a substituição de texto em Haskell simples, sem a complicação de expressões regulares quase citadas.
Com 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"