Wie geben Sie ein Regex-Muster in Haskell an?
Ich versuche, einen regulären Ausdruck durch den folgenden Code zu ersetzen
import Text.RE.Replace
import Text.RE.TDFA.String
onlyLetters :: String -> String
onlyLetters s = replaceAll "" $ s *=~ [re|$([^a-zA-Z])|]
Es fiel mir wirklich schwer, eine nachvollziehbare Dokumentation dazu zu finden. Dies erzeugt den Kompilierungsfehler:
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
Was ist das Problem mit dieser Klammer und wie würde ich das richtig machen? Danke -Skye
Antworten
Das […|…|]
ist quasi Zitatsyntax [haskell-wiki] . Dies ist eine Erweiterung der Haskell-Syntax und nicht standardmäßig aktiviert.
Sie können dies mit einem LANGUAGE
Pragma aktivieren:
{-# LANGUAGE QuasiQuotes #-}
import Text.RE.Replace
import Text.RE.TDFA.String
onlyLetters :: String -> String
onlyLetters s = replaceAll "" $ s *=~ [re|$([^a-zA-Z])|]
Die Quasiquoten generieren Haskell-Code, der dann im Haskell-Programm verwendet wird. Dies bedeutet, dass durch die Quasiquoten die Validierung des regulären Ausdrucks zur Kompilierungszeit erfolgen kann und die Effizienz im Vergleich zum Kompilieren des regulären Ausdrucks zur Laufzeit sogar geringfügig optimiert werden kann.
Für die gegebene onlyLetters
Funktion erhalten wir dann:
*Main> onlyLetters "fo0b4r"
"fobr"
Die Antwort von Willem Van Onsem ist eine bessere Antwort auf die Frage, aber ich werde eine Antwort vorschlagen , die dies stattdessen versucht .
Auf diese Weise können Sie die Textersetzung in einfachem Haskell durchführen, ohne dass es zu Quasi-Anführungszeichen kommt.
Mit 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"