Easy switch between lazy and strict ByteString

657 views Asked by At

I need to work with strict and lazy ByteStrings, because this is the requirement preset by the choice of libraries (some mix of happstack, base64, sha256, hexpat, etc.). After some dancing with "fromStrict" and similar I ended up with this:

import qualified Data.ByteString.Char8  as S
import qualified Data.ByteString.Lazy.Char8  as L

class BString s where
  lazy :: s -> L.ByteString
  strict :: s -> S.ByteString
  pack :: String -> s
  text :: T.Text -> s

instance BString L.ByteString where
  lazy = id
  strict = S.concat . L.toChunks
  pack = L.pack
  text = L.fromStrict . TE.encodeUtf8

instance BString S.ByteString where
  lazy = L.fromStrict
  strict = id
  pack = S.pack
  text = TE.encodeUtf8 

so that I just put "lazy $" when the library function in hands requires lazy byte string or "strict $" in case of strict version. That works fine, costing an occasional conversion though, but it feels like I've invented bicycle here.

So, the question is if there's a better (shorter, statically typed, more effective) alternative to such code? Is there a library trying to uniform lazy/strict handling? Or maybe I'm doing a wrong thing and it's considered a bad practice (thou shall not convert between lazy and strict or something)?

Thanks.

1

There are 1 answers

2
ErikR On

I would write an adaption layer between your application and these libraries to perform all of the necessary conversions. Design the adaptation layer so that you use your preferred application data types as input and output to those functions.

Once you have chosen your modules the signatures of the library functions are never going to change. That is, you know what kind of string a call to base64 encode will return (by your choice of module.) Therefore, if you need to plumb together two library functions you know exactly what conversions need to be made to fit the two together.