Prefissi di stringa corrispondenti al modello in Haskell
-
05-07-2019 - |
Domanda
Diciamo che voglio creare un caso speciale per una funzione che corrisponda a stringhe che iniziano con il carattere 'Z'. Potrei facilmente farlo usando il pattern matching facendo qualcosa di simile al seguente:
myfunc ('Z' : restOfString) = -- do something special
myfunc s = -- do the default case here
Ma cosa succede se voglio abbinare le stringhe con un prefisso più lungo? Supponiamo di voler avere un caso speciale per le stringhe che iniziano con la parola "tostapane". Qual è il modo migliore per scrivere un modello per abbinare una tale stringa?
Soluzione
myfunc ('t':'o':'a':'s':'t':'e':'r' : restOfString) = ...
L'uso di una corrispondenza di pattern normale funziona, ma diventa fastidioso man mano che la stringa del prefisso si allunga.
{-# LANGUAGE PatternGuards #-}
import Data.List
myFunc string | Just restOfString <- stripPrefix "toaster" string =
-- do something special
myFunc string = -- do the default case here
L'uso di una funzione di libreria anziché di una corrispondenza di pattern è un po 'più facile da leggere e scrivere.
{-# LANGUAGE ViewPatterns #-}
import Data.List
myFunc (stripPrefix "toaster" -> Just restOfString) = -- do something special
myFunc string = -- do the default case here
Un'estensione della sintassi di GHC 6.10 rende questo utilizzo ancora più naturale.
Naturalmente, gli ultimi due sono completamente equivalenti e possiamo accontentarci (in modo disordinato) senza zucchero.
import Data.List
myFunc string =
if restIsJust
then -- do something special
else -- do the default case here
where
(restIsJust, restOfString) =
case stripPrefix "toaster" string of
Just something -> (True, something)
Nothing -> (False, undefined)
Quelle estensioni di sintassi sono pensate per semplificarci la vita.
Altri suggerimenti
import Data.List
myFunc str | "toaster" `isPrefixOf` str = something restOfString
| otherwise = somethingElse
where Just restOfString = stripPrefix "toaster" str
La libreria Split, http://hackage.haskell.org/packages/archive/split/0.1.1/doc/html/Data-List-Split.html ha molte funzioni per dividere le stringhe con le stringhe, inclusa la corrispondenza del prefisso. Potresti trovare qualcosa di utile lì.
myfunc ('t' : 'o' : 'a' : 's' : 't' : 'e' : 'r' : restOfString)
Per quanto ne so, non esiste sintassi più concisa di quella.
Ovviamente puoi anche verificare se la stringa inizia con un tostapane in una clausola di protezione o un se
all'interno del corpo della funzione.
myFunc str =
case stripPrefix "toaster" str of
Just restOfString -> something restOfString
Nothing -> somethingElse
Ecco perché stripPrefix restituisce un tipo Maybe.