В последней версии GHC (7.8) есть функция, называемая шаблонными синонимами, которую можно добавить в пример gawi:
{-# LANGUAGE ViewPatterns, PatternSynonyms #-}
import Data.ByteString (ByteString, cons, uncons, singleton, empty)
import Data.ByteString.Internal (c2w)
infixr 5 :<
pattern b :< bs <- (uncons -> Just (b, bs))
pattern Empty <- (uncons -> Nothing)
dropR :: ByteString -> ByteString
dropR Empty = empty
dropR (x :< Empty) = singleton x
dropR (x :< y :< xs)
| x == c2w 'a' && y == c2w 'b' = dropR xs
| otherwise = cons x (dropR (cons y xs))
Если пойти дальше, вы можете абстрагировать это для работы с любым классом типов (это будет выглядеть лучше, когда / если мы получим синонимов связанных шаблонов ). Определения шаблонов остаются прежними:
{-# LANGUAGE ViewPatterns, PatternSynonyms, TypeFamilies #-}
import qualified Data.ByteString as BS
import Data.ByteString (ByteString, singleton)
import Data.ByteString.Internal (c2w)
import Data.Word
class ListLike l where
type Elem l
empty :: l
uncons :: l -> Maybe (Elem l, l)
cons :: Elem l -> l -> l
instance ListLike ByteString where
type Elem ByteString = Word8
empty = BS.empty
uncons = BS.uncons
cons = BS.cons
instance ListLike [a] where
type Elem [a] = a
empty = []
uncons [] = Nothing
uncons (x:xs) = Just (x, xs)
cons = (:)
, в этом случае dropR
может работать как на [Word8]
, так и на ByteString
:
-- dropR :: [Word8] -> [Word8]
-- dropR :: ByteString -> ByteString
dropR :: (ListLike l, Elem l ~ Word8) => l -> l
dropR Empty = empty
dropR (x :< Empty) = cons x empty
dropR (x :< y :< xs)
| x == c2w 'a' && y == c2w 'b' = dropR xs
| otherwise = cons x (dropR (cons y xs))
И, черт возьми, это:
import Data.ByteString.Internal (w2c)
infixr 5 :•
pattern b :• bs <- (w2c -> b) :< bs
dropR :: (ListLike l, Elem l ~ Word8) => l -> l
dropR Empty = empty
dropR (x :< Empty) = cons x empty
dropR ('a' :• 'b' :• xs) = dropR xs
dropR (x :< y :< xs) = cons x (dropR (cons y xs))
Вы можете увидеть больше на моем посте по синонимам паттернов.