string-convert-3.0.1: Text/StringConvert.hs
-- | Provides universal conversions between any two string-like types.
-- Out-of-the-box, @Text@ (both lazy and strict), @ByteString@ (both lazy and
-- strict), and String, are supported.
--
-- To hook custom string types into the conversion mechanism, implement both
-- @FromString@ and @ToString@ for your type.
{-#LANGUAGE FlexibleInstances #-}
module Text.StringConvert
( FromString
, fromString
, ToString
, toString
, s
)
where
import qualified Data.Text as Text
import qualified Data.Text.Lazy as LText
import qualified Data.ByteString.UTF8 as UTF8
import qualified Data.ByteString.Lazy.UTF8 as LUTF8
import qualified Data.ByteString.Lazy as LBS
class FromString a where
fromString :: String -> a
instance FromString [Char] where
fromString = id
instance FromString Text.Text where
fromString = Text.pack
instance FromString LText.Text where
fromString = LText.pack
instance FromString UTF8.ByteString where
fromString = UTF8.fromString
instance FromString LUTF8.ByteString where
fromString = LUTF8.fromString
-- | Defines how a given type should be converted to String.
-- If at all possible, the conversion should be loss-less, and if encodings are
-- involved, UTF-8 should be the default.
class ToString a where
toString :: a -> String
instance ToString [Char] where
toString = id
instance ToString LText.Text where
toString = LText.unpack
instance ToString Text.Text where
toString = Text.unpack
instance ToString UTF8.ByteString where
toString = UTF8.toString
instance ToString LUTF8.ByteString where
toString = LUTF8.toString
-- if the conversion is a no-op, rewrite it as id
{-# RULES "s/same-type" s = id #-}
-- conversions between strict and lazy texts can be done directly
{-# RULES "s/LText->Text" s = LText.toStrict #-}
{-# RULES "s/Text->LText" s = LText.fromStrict #-}
-- conversions between strict and lazy bytestrings can be done directly
{-# RULES "s/LBS->BS" s = LBS.toStrict #-}
{-# RULES "s/BS->LBS" s = LBS.fromStrict #-}
-- conversions to and from string can be done through the ToString / FromString
-- classes
{-# RULES "s/->String" s = toString #-}
{-# RULES "s/String->" s = fromString #-}
{-# NOINLINE s #-}
s :: (ToString a, FromString b) => a -> b
s = fromString . toString