{-# LANGUAGE ExplicitForAll #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE UndecidableInstances #-} {-| Assuming UTF8 encoding the following types are isomorphic - Data.ByteString.Lazy.ByteString - Data.ByteString.ByteString - Data.Text.Lazy.Text - Data.Text.Text - String Yet working with them and converting is a pain! This package exposes this 5 way isomorphism to make conversion easy. -} module Text.Isomorphic ( module Data.Types.Injective , module Data.Types.Isomorphic , as, as2, as3, as4 ) where import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as BSC import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString.Lazy.Char8 as BLC import qualified Data.Char as C import qualified Data.String as S import qualified Data.Text as TS import qualified Data.Text.Encoding as TSE import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy.Encoding as TLE import Data.Types.Injective import Data.Types.Isomorphic instance {-# OVERLAPPABLE #-} S.IsString s => Injective String s where to = S.fromString instance Injective BS.ByteString String where to = BSC.unpack {-# INLINE to #-} instance Injective String BS.ByteString where to = BSC.pack {-# INLINE to #-} instance Iso String BS.ByteString instance Iso BS.ByteString String instance Injective BL.ByteString String where to = BLC.unpack {-# INLINE to #-} instance Injective String BL.ByteString where to = BLC.pack {-# INLINE to #-} instance Iso String BL.ByteString instance Iso BL.ByteString String instance Injective TS.Text BS.ByteString where to = TSE.encodeUtf8 {-# INLINE to #-} instance Injective BS.ByteString TS.Text where to = TSE.decodeUtf8 {-# INLINE to #-} instance Iso TS.Text BS.ByteString instance Iso BS.ByteString TS.Text instance Injective TS.Text BL.ByteString where to = BL.fromStrict . to {-# INLINE to #-} instance Injective BL.ByteString TS.Text where to = to . BL.toStrict {-# INLINE to #-} instance Iso TS.Text BL.ByteString instance Iso BL.ByteString TS.Text instance Injective TL.Text BS.ByteString where to = BL.toStrict . to {-# INLINE to #-} instance Injective BS.ByteString TL.Text where to = to . BL.fromStrict {-# INLINE to #-} instance Iso TL.Text BS.ByteString instance Iso BS.ByteString TL.Text instance Injective TL.Text BL.ByteString where to = TLE.encodeUtf8 {-# INLINE to #-} instance Injective BL.ByteString TL.Text where to = TLE.decodeUtf8 {-# INLINE to #-} instance Iso TL.Text BL.ByteString instance Iso BL.ByteString TL.Text instance Injective BS.ByteString BL.ByteString where to = BL.fromStrict {-# INLINE to #-} instance Injective BL.ByteString BS.ByteString where to = BL.toStrict {-# INLINE to #-} instance Iso BS.ByteString BL.ByteString instance Iso BL.ByteString BS.ByteString {-| This is useful for any iso, but in the case of string like stuff. You can now work with a function from one string type, while not having to do any conversion. @ f :: ByteString -> ByteString a :: Text as f a :: Text @ -} as :: forall a b. (Iso a b, Iso b a) => (a -> a) -> b -> b as f = from . f . to {-# INLINABLE as #-} {-| Like @liftA2@ -} as2 :: forall a b. (Iso a b, Iso b a) => (a -> a -> a) -> b -> b -> b as2 f x y = from $ f (to x) (to y) {-| Like @liftA3@ -} as3 :: forall a b. (Iso a b, Iso b a) => (a -> a -> a -> a) -> b -> b -> b -> b as3 f x y z = from $ f (to x) (to y) (to z) {-| Like @liftA4@ -} as4 :: forall a b. (Iso a b, Iso b a) => (a -> a -> a -> a -> a) -> b -> b -> b -> b -> b as4 f w x y z = from $ f (to w) (to x) (to y) (to z)