Patrón de coincidencia de prefijos de cadena en Haskell
-
05-07-2019 - |
Pregunta
Digamos que quiero crear un caso especial para una función que coincida con las cadenas que comienzan con el carácter 'Z'. Podría hacerlo fácilmente utilizando la coincidencia de patrones haciendo algo como lo siguiente:
myfunc ('Z' : restOfString) = -- do something special
myfunc s = -- do the default case here
Pero, ¿qué pasa si quiero hacer coincidir cadenas con un prefijo más largo? Digamos que quiero tener un caso especial para cadenas que comiencen con la palabra "tostador". ¿Cuál es la mejor manera de escribir un patrón para que coincida con esa cadena?
Solución
myfunc ('t':'o':'a':'s':'t':'e':'r' : restOfString) = ...
El uso de una coincidencia de patrón normal funciona, pero se vuelve molesto a medida que la cadena de prefijo se alarga.
{-# LANGUAGE PatternGuards #-}
import Data.List
myFunc string | Just restOfString <- stripPrefix "toaster" string =
-- do something special
myFunc string = -- do the default case here
Usar una función de biblioteca en lugar de una coincidencia de patrón es un poco más fácil de leer y escribir.
{-# LANGUAGE ViewPatterns #-}
import Data.List
myFunc (stripPrefix "toaster" -> Just restOfString) = -- do something special
myFunc string = -- do the default case here
Una extensión de sintaxis GHC 6.10 hace que este uso sea aún más natural.
Por supuesto, los dos últimos son completamente equivalentes, y podemos hacerlo (desordenadamente) sin ningún tipo de azúcar.
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)
Sin embargo, esas extensiones de sintaxis están destinadas a hacernos la vida más fácil.
Otros consejos
import Data.List
myFunc str | "toaster" `isPrefixOf` str = something restOfString
| otherwise = somethingElse
where Just restOfString = stripPrefix "toaster" str
La biblioteca dividida, http://hackage.haskell.org/packages/archive/split/0.1.1/doc/html/Data-List-Split.html tiene muchas funciones para dividir cadenas con cadenas, incluida la coincidencia de prefijos. Puede que encuentres algo útil allí.
myfunc ('t' : 'o' : 'a' : 's' : 't' : 'e' : 'r' : restOfString)
Que yo sepa, no hay una sintaxis más concisa que esa.
Por supuesto, también puede verificar si la cadena comienza con el tostador en una cláusula de protección o si
dentro del cuerpo de la función.
myFunc str =
case stripPrefix "toaster" str of
Just restOfString -> something restOfString
Nothing -> somethingElse
Este es el motivo por el que stripPrefix devuelve un tipo Maybe.