I'm a Haskell newbie, and having a bit of trouble figuring out how to pattern match a ByteString
. The [Char]
version of my function looks like:
dropAB :: String -> String
dropAB [] = []
dropAB (x:[]) = x:[]
dropAB (x:y:xs) = if x=='a' && y=='b'
then dropAB xs
else x:(dropAB $ y:xs)
As expected, this filters out all occurrences of "ab" from a string. However, I have problems trying to apply this to a ByteString
.
The naive version
dropR :: BS.ByteString -> BS.ByteString
dropR [] = []
dropR (x:[]) = [x]
<...>
yields
Couldn't match expected type `BS.ByteString'
against inferred type `[a]'
In the pattern: []
In the definition of `dropR': dropR [] = []
[]
is clearly the culprit, as it is for a regular String
not a ByteString
. Subbing in BS.empty
seems like the right thing but gives "Qualified name in the binding position: BS.empty." Leaving us to try
dropR :: BS.ByteString -> BS.ByteString
dropR empty = empty
dropR (x cons empty) = x cons empty
<...>
this gives "parse error in pattern" for (x cons empty)
. I don't really know what else I can do here.
As a side note, what I'm trying to do with this function is to filter out a specific UTF16 character from some text. If there's a clean way to accomplish that, I'd love to hear it, but this pattern matching error seems like something that a newbie haskeller should really understand.
You can use view patterns for such things
{-# LANGUAGE ViewPatterns #-}
import Data.ByteString (ByteString, cons, uncons, singleton, empty)
import Data.ByteString.Internal (c2w)
dropR :: ByteString -> ByteString
dropR (uncons -> Nothing) = empty
dropR (uncons -> Just (x,uncons -> Nothing)) = singleton x
dropR (uncons -> Just (x,uncons -> Just(y,xs))) =
if x == c2w 'a' && y == c2w 'b'
then dropR xs
else cons x (dropR $ cons y xs)