2009-10-21 13 views
16

Załóżmy, że chcę utworzyć specjalny przypadek dla funkcji pasującej do ciągów zaczynających się od znaku "Z". Mógłbym łatwo zrobić za pomocą dopasowywania wzorców wykonując coś tak:Prefiksy ciągów pasujących do wzorca w języku Haskell

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

ale co, jeśli chcę, aby dopasować ciągi z dłuższym prefiks? Powiedzmy, że chcę mieć specjalny przypadek dla ciągów, które zaczynają się od słowa "toster". Jaki jest najlepszy sposób na napisanie wzoru pasującego do takiego ciągu?

+0

Odręcznie wygląda całkiem prosto napisać i wywołać szablon Haskell, aby osiągnąć pożądany efekt. Jednak nie jestem wystarczającą osobą TH. –

+0

Niestety, GHC nie implementuje splotów wzorcowych (o ile mi wiadomo, jest to naprawdę trudne), więc nie jest to możliwe. – ephemient

Odpowiedz

29
myfunc ('t':'o':'a':'s':'t':'e':'r' : restOfString) = ... 

Korzystanie z normalnego dopasowania do wzoru działa, ale staje się kłopotliwe, ponieważ ciąg prefiksu jest dłuższy.

Używanie funkcji bibliotecznej zamiast dopasowania wzoru jest nieco łatwiejsze do odczytania i napisania.

{-# LANGUAGE ViewPatterns #-} 
import Data.List 
myFunc (stripPrefix "toaster" -> Just restOfString) = -- do something special 
myFunc string = -- do the default case here 

Rozszerzenie składni GHC 6.10 czyni to użycie jeszcze bardziej naturalnym.


Oczywiście, te dwa ostatnie są sobie równe, a możemy zrobić (niechlujnie) bez cukru w ​​ogóle.

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) 

Te rozszerzenia składni mają jednak ułatwić życie.

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

O ile mi wiadomo, nie ma bardziej zwięzłej składni.

Oczywiście można również sprawdzić, czy sznur zaczyna się od tostera w klauzuli ochronnej lub if w korpusie funkcji.

8
import Data.List 

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

Najpierw myślałem o czymś takim, ale wydaje się głupie, że muszę dwa razy pisać "toster". – ephemient

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

Dlatego stripPrefix zwraca typ być może.