32

假设我想为匹配以字符“Z”开头的字符串的函数创建一个特殊情况。我可以通过执行以下操作轻松地使用模式匹配来做到这一点:

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

但是如果我想匹配带有更长前缀的字符串呢?假设我想对以单词“toaster”开头的字符串有一个特殊的情况。编写模式以匹配这样的字符串的最佳方法是什么?

4

5 回答 5

41
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)

不过,这些语法扩展旨在让我们的生活更轻松。

于 2009-10-21T17:24:28.843 回答
9
import Data.List

myFunc str | "toaster" `isPrefixOf` str = something restOfString
           | otherwise = somethingElse
    where Just restOfString = stripPrefix "toaster" str
于 2009-10-21T18:06:27.417 回答
6

Split 库,http://hackage.haskell.org/packages/archive/split/0.1.1/doc/html/Data-List-Split.html有很多函数可以用字符串分割字符串,包括前缀匹配。你可能会在那里找到一些有用的东西。

于 2009-10-21T20:37:47.330 回答
5
myfunc ('t' : 'o' : 'a' : 's' : 't' : 'e' : 'r' : restOfString)

据我所知,没有比这更简洁的语法了。

if当然,您也可以只检查字符串是在保护子句中还是以函数体内部的toaster 开头。

于 2009-10-21T17:23:58.937 回答
4
myFunc str =
  case stripPrefix "toaster" str of
     Just restOfString -> something restOfString
     Nothing -> somethingElse

这就是 stripPrefix 返回 Maybe 类型的原因。

于 2010-06-11T19:36:16.143 回答