假设我想为匹配以字符“Z”开头的字符串的函数创建一个特殊情况。我可以通过执行以下操作轻松地使用模式匹配来做到这一点:
myfunc ('Z' : restOfString) = -- do something special
myfunc s = -- do the default case here
但是如果我想匹配带有更长前缀的字符串呢?假设我想对以单词“toaster”开头的字符串有一个特殊的情况。编写模式以匹配这样的字符串的最佳方法是什么?
假设我想为匹配以字符“Z”开头的字符串的函数创建一个特殊情况。我可以通过执行以下操作轻松地使用模式匹配来做到这一点:
myfunc ('Z' : restOfString) = -- do something special
myfunc s = -- do the default case here
但是如果我想匹配带有更长前缀的字符串呢?假设我想对以单词“toaster”开头的字符串有一个特殊的情况。编写模式以匹配这样的字符串的最佳方法是什么?
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)
不过,这些语法扩展旨在让我们的生活更轻松。
import Data.List
myFunc str | "toaster" `isPrefixOf` str = something restOfString
| otherwise = somethingElse
where Just restOfString = stripPrefix "toaster" str
Split 库,http://hackage.haskell.org/packages/archive/split/0.1.1/doc/html/Data-List-Split.html有很多函数可以用字符串分割字符串,包括前缀匹配。你可能会在那里找到一些有用的东西。
myfunc ('t' : 'o' : 'a' : 's' : 't' : 'e' : 'r' : restOfString)
据我所知,没有比这更简洁的语法了。
if
当然,您也可以只检查字符串是在保护子句中还是以函数体内部的toaster 开头。
myFunc str =
case stripPrefix "toaster" str of
Just restOfString -> something restOfString
Nothing -> somethingElse
这就是 stripPrefix 返回 Maybe 类型的原因。