diff --git a/benchmark/Main.hs b/benchmark/Main.hs index 5c3543a..187cfa4 100644 --- a/benchmark/Main.hs +++ b/benchmark/Main.hs @@ -24,6 +24,7 @@ main = defaultMain , bgroupConcatMap , bgroupMember , bgroupFold + , bgroupTextConversion ] bgroupList :: forall a . @@ -171,3 +172,8 @@ bgroupFold = do bgroup "foldl'" [ bench "flipped" $ nf flipFoldl' testList , bench "base" $ nf ghcFoldl' testList ] + +bgroupTextConversion :: Benchmark +bgroupTextConversion = + let str = replicate 100000 'a' + in bench "toText/toString" $ whnf (length . toString . toText) str diff --git a/src/Universum/String/Conversion.hs b/src/Universum/String/Conversion.hs index 877022d..f6c0a9b 100644 --- a/src/Universum/String/Conversion.hs +++ b/src/Universum/String/Conversion.hs @@ -124,15 +124,19 @@ instance ConvertUtf8 LT.Text LB.ByteString where class ToText a where toText :: a -> T.Text -instance ToText String where - toText = T.pack - instance ToText T.Text where toText = id instance ToText LT.Text where toText = LT.toStrict +instance ToText String where + toText = stringToText + +stringToText :: String -> Text +stringToText = T.pack +{-# NOINLINE [4] stringToText #-} + -- | Type class for converting other strings to 'LT.Text'. class ToLText a where toLText :: a -> LT.Text @@ -153,12 +157,22 @@ class ToString a where instance ToString String where toString = id -instance ToString T.Text where - toString = T.unpack - instance ToString LT.Text where toString = LT.unpack +instance ToString T.Text where + toString = textToString + +textToString :: Text -> String +textToString = T.unpack +{-# NOINLINE [4] textToString #-} + +-- This pattern may occur quite often because we tend to use 'Text' +-- rather than 'String' in function signatures. +{-# RULES +"toString/toText" [~3] forall a. textToString (stringToText a) = a +#-} + -- | Polymorhpic version of 'Text.Read.readEither'. -- -- >>> readEither @Text @Int "123" diff --git a/test/Test/Universum/Property.hs b/test/Test/Universum/Property.hs index ad43263..612088a 100644 --- a/test/Test/Universum/Property.hs +++ b/test/Test/Universum/Property.hs @@ -2,28 +2,32 @@ module Test.Universum.Property ( hedgehogTestTree ) where -import Universum +import Universum +import qualified Universum as U import Data.List (nub) -import Hedgehog (Property, Gen, MonadGen, forAll, property, assert, (===)) -import Test.Tasty (testGroup, TestTree) +import Hedgehog (Gen, MonadGen, Property, assert, forAll, property, (===)) +import Test.Tasty (TestTree, testGroup) import Test.Tasty.Hedgehog -import qualified Universum as U -import qualified Hedgehog.Gen as Gen -import qualified Hedgehog.Range as Range -import qualified Data.ByteString as B -import qualified Data.ByteString.Lazy as LB -import qualified Data.Text as T -import qualified Data.Text.Lazy as LT - +import qualified Data.ByteString as B +import qualified Data.ByteString.Lazy as LB +import qualified Data.Text as T +import qualified Data.Text.Lazy as LT +import qualified Hedgehog.Gen as Gen +import qualified Hedgehog.Range as Range hedgehogTestTree :: TestTree -hedgehogTestTree = testGroup "Tests" [utfProps, listProps, boolMProps] +hedgehogTestTree = testGroup "Tests" [stringProps, utfProps, listProps, boolMProps] + +stringProps :: TestTree +stringProps = testGroup "String conversions" + [ testProperty "toString . toText = id" prop_StringToTextAndBack + ] utfProps :: TestTree -utfProps = testGroup "utf8 conversion property tests" +utfProps = testGroup "utf8 conversion property tests" [ testProperty "String to ByteString invertible" prop_StringToBytes , testProperty "Text to ByteString invertible" prop_TextToBytes , testProperty "ByteString to Text or String invertible" prop_BytesTo @@ -48,7 +52,12 @@ utf8Bytes = Gen.utf8 (Range.linear 0 10000) unicode' -- "\65534" fails, but this is from BU.toString -- > import qualified Data.ByteString.UTF8 as BU -- > BU.toString (BU.fromString "\65534") == "\65533" --- > True +-- > True + +prop_StringToTextAndBack :: Property +prop_StringToTextAndBack = property $ do + str <- forAll utf8String + toString (toText str) === str prop_StringToBytes :: Property prop_StringToBytes = property $ do @@ -74,7 +83,7 @@ prop_BytesTo = property $ do -- ordNub listProps :: TestTree -listProps = testGroup "list function property tests" +listProps = testGroup "list function property tests" [ testProperty "Hedgehog ordNub xs == nub xs" prop_ordNubCorrect , testProperty "Hedgehog hashNub xs == nub xs" prop_hashNubCorrect , testProperty "Hedgehog sortNub xs == sort $ nub xs" prop_sortNubCorrect @@ -126,4 +135,3 @@ prop_orM :: Property prop_orM = property $ do bs <- forAll genBoolList U.orM (return <$> bs) === ((return $ U.or bs) :: U.Maybe U.Bool) -