2009-10-21 65 views
16

假設我想爲匹配以字符'Z'開頭的字符串的函數做一個特殊情況。我可以很容易做到這一點通過執行類似下面的使用模式匹配:Haskell中的模式匹配字符串前綴

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

但是,如果我想有更長的前綴匹配字符串是什麼?假設我想爲以「烤麪包機」一詞開頭的字符串開一個特例。編寫匹配這樣的字符串的模式的最佳方法是什麼?

+0

非常簡單,編寫並調用模板哈斯克爾來達到預期的效果。儘管如此,我還不足以確定一個TH人。 – 2009-10-22 06:55:38

+0

不幸的是,GHC沒有實現模式拼接(據我所知,顯然它很難),所以這是不可能的。 – ephemient 2009-10-22 18:18:19

回答

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

使用正常模式匹配工作,但由於前綴字符串變長而變得麻煩。

{-# LANGUAGE PatternGuards #-} 
import Data.List 
myFunc string | Just restOfString <- stripPrefix "toaster" string = 
    -- do something special 
myFunc string = -- do the default case here 

使用庫函數而不是模式匹配可以更容易讀取和寫入。

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

GHC 6.10語法擴展使得這種用法更加自然。


當然,後兩者是完全等價的,我們可以在沒有任何糖的情況下做(混亂地)。

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) 

雖然這些語法擴展是爲了讓我們的生活更輕鬆。

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

據我所知,沒有比這更簡潔的語法。

您當然也可以檢查字符串是以guard-clause中的烤麪包機還是以函數體內的if開頭。

8
import Data.List 

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

我在想第一個這樣的東西,但是必須兩次寫'烤麪包機'似乎很愚蠢。 – ephemient 2009-10-21 20:00:07

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

這就是爲什麼stripPrefix返回一個Maybe類型。