2009-10-21 6 views
16

Digamos que quiero hacer un caso especial para una función que coincida con cadenas que comiencen con el carácter 'Z'. Yo podría hacerlo utilizando la coincidencia de patrones haciendo algo como lo siguiente:Prefijos de cadenas coincidentes en Haskell

myfunc ('Z' : restOfString) = -- do something special 
myfunc s = -- do the default case here 

Pero lo que si quiero hacer coincidir cadenas de prefijo mayor? Digamos que quiero tener un caso especial para cadenas que comiencen con la palabra "tostadora". ¿Cuál es la mejor manera de escribir un patrón para que coincida con una cuerda?

+0

Offhand parece bastante sencillo escribir e invocar Template Haskell para lograr el efecto deseado. Sin embargo, no soy suficiente de una persona TH para estar seguro. –

+0

Desafortunadamente, GHC no implementa empalmes de patrones (hasta donde sé, aparentemente es muy difícil), así que esto no es posible. – ephemient

Respuesta

29
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 (desordenado) sin azúcar en absoluto.

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 hechas para facilitarnos la vida.

3
myfunc ('t' : 'o' : 'a' : 's' : 't' : 'e' : 'r' : restOfString) 

Por lo que yo sé, no hay más sintaxis sucinta que eso.

Por supuesto, también puede comprobar si la cadena comienza con tostador en una cláusula de guardia o if dentro del cuerpo de la función.

8
import Data.List 

myFunc str | "toaster" `isPrefixOf` str = something restOfString 
      | otherwise = somethingElse 
    where Just restOfString = stripPrefix "toaster" str 
+2

Estaba pensando en algo así primero, pero parece una tontería tener que escribir '" tostadora "' dos veces. – ephemient

3
myFunc str = 
    case stripPrefix "toaster" str of 
    Just restOfString -> something restOfString 
    Nothing -> somethingElse 

Es por esto que stripPrefix devuelve un tipo Maybe.

Cuestiones relacionadas