2009-10-21 4 views
16

Предположим, я хочу создать специальный случай для функции, которая соответствует строкам, начинающимся с символа «Z». Я мог бы легко сделать это с помощью сопоставления с образцом, делая что-то вроде следующего:Соответствующие строковые префиксы шаблонов в Haskell

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

Но что, если я хочу, чтобы соответствовать строки с более длинным префиксом? Скажем, я хочу иметь специальный случай для строк, которые начинаются со слова «тостер». Каков наилучший способ написать шаблон для соответствия такой строке?

+0

Оффлайн выглядит довольно простым для написания и вызова шаблона Haskell для достижения желаемого эффекта. Впрочем, я недостаточно того, чтобы человек был уверен. – 2009-10-22 06:55:38

+0

К сожалению, GHC не реализует сращивания шаблонов (насколько я знаю, по-видимому, это очень сложно), поэтому это невозможно. – ephemient

ответ

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) 

Насколько мне известно, более сильного синтаксиса больше нет.

Вы можете, конечно, также просто проверить, начинается ли строка с тостера в защитном предложении или if внутри тела функции.

8
import Data.List 

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

Сначала я думал о чем-то подобном, но мне кажется глупо писать «тостер» дважды. – ephemient

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

Именно поэтому stripPrefix возвращает тип Maybe.