Строковые префиксы сопоставления с образцом в Haskell
-
05-07-2019 - |
Вопрос
Допустим, я хочу сделать специальный случай для функции, которая соответствует строкам, начинающимся с символа 'Z'. Я мог бы легко сделать это, используя сопоставление с образцом, выполнив что-то вроде следующего:
myfunc ('Z' : restOfString) = -- do something special
myfunc s = -- do the default case here
Но что, если я хочу сопоставить строки с более длинным префиксом? Скажем, я хочу иметь особый случай для строк, начинающихся со слова «тостер». Какой лучший способ написать шаблон для сопоставления с такой строкой?
Решение
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)
Насколько я знаю, нет более краткого синтаксиса, чем этот.
Конечно, вы также можете просто проверить, начинается ли строка с тостера в предложении guard или if
внутри тела функции.
myFunc str =
case stripPrefix "toaster" str of
Just restOfString -> something restOfString
Nothing -> somethingElse
Вот почему stripPrefix возвращает тип Maybe.