Préfixes de chaînes de correspondance de modèle dans Haskell
-
05-07-2019 - |
Question
Supposons que je souhaite créer un cas spécial pour une fonction qui correspond aux chaînes commençant par le caractère 'Z'. Je pourrais facilement le faire en utilisant une correspondance de modèle en procédant comme suit:
myfunc ('Z' : restOfString) = -- do something special
myfunc s = -- do the default case here
Mais que faire si je veux faire correspondre les chaînes avec un préfixe plus long? Dites que je veux avoir un cas particulier pour les chaînes qui commencent par le mot "grille-pain". Quel est le meilleur moyen d’écrire un modèle pour correspondre à une telle chaîne?
La solution
myfunc ('t':'o':'a':'s':'t':'e':'r' : restOfString) = ...
L'utilisation d'une correspondance de modèle normale fonctionne, mais devient gênante à mesure que la chaîne de préfixe s'allonge.
{-# LANGUAGE PatternGuards #-}
import Data.List
myFunc string | Just restOfString <- stripPrefix "toaster" string =
-- do something special
myFunc string = -- do the default case here
L'utilisation d'une fonction de bibliothèque au lieu d'une correspondance de modèle est un peu plus facile à lire et à écrire.
{-# LANGUAGE ViewPatterns #-}
import Data.List
myFunc (stripPrefix "toaster" -> Just restOfString) = -- do something special
myFunc string = -- do the default case here
Une extension de syntaxe GHC 6.10 rend cette utilisation encore plus naturelle.
Bien sûr, les deux derniers sont complètement équivalents, et nous pouvons nous débrouiller sans aucun sucre.
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)
Ces extensions de syntaxe sont conçues pour nous simplifier la vie.
Autres conseils
import Data.List
myFunc str | "toaster" `isPrefixOf` str = something restOfString
| otherwise = somethingElse
where Just restOfString = stripPrefix "toaster" str
La bibliothèque Split, http://hackage.haskell.org/packages/archive/split/0.1.1/doc/html/Data-List-Split.html offre de nombreuses fonctions pour fractionner des chaînes avec des chaînes, y compris la correspondance du préfixe. Vous y trouverez peut-être quelque chose d'utile.
myfunc ('t' : 'o' : 'a' : 's' : 't' : 'e' : 'r' : restOfString)
Autant que je sache, il n’existe pas de syntaxe plus succincte que celle-là.
Vous pouvez bien sûr aussi simplement vérifier si la chaîne commence par toaster dans une clause de garde ou un if
dans le corps de la fonction.
myFunc str =
case stripPrefix "toaster" str of
Just restOfString -> something restOfString
Nothing -> somethingElse
C’est pourquoi stripPrefix renvoie un type Maybe.