packages feed

isomorphism-class (empty) → 0.1

raw patch · 7 files changed

+929/−0 lines, 7 filesdep +QuickCheckdep +basedep +bytestring

Dependencies added: QuickCheck, base, bytestring, containers, hashable, isomorphism-class, primitive, quickcheck-instances, rebase, tasty, tasty-hunit, tasty-quickcheck, text, unordered-containers, vector

Files

+ LICENSE view
@@ -0,0 +1,22 @@+Copyright (c) 2022 Nikita Volkov++Permission is hereby granted, free of charge, to any person+obtaining a copy of this software and associated documentation+files (the "Software"), to deal in the Software without+restriction, including without limitation the rights to use,+copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the+Software is furnished to do so, subject to the following+conditions:++The above copyright notice and this permission notice shall be+included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR+OTHER DEALINGS IN THE SOFTWARE.
+ isomorphism-class.cabal view
@@ -0,0 +1,65 @@+cabal-version: 3.0++name: isomorphism-class+version: 0.1+synopsis: Isomorphism typeclass solving the conversion problem+homepage: https://github.com/nikita-volkov/isomorphism-class+bug-reports: https://github.com/nikita-volkov/isomorphism-class/issues+author: Nikita Volkov <nikita.y.volkov@mail.ru>+maintainer: Nikita Volkov <nikita.y.volkov@mail.ru>+copyright: (c) 2022 Nikita Volkov+license: MIT+license-file: LICENSE++source-repository head+  type: git+  location: git://github.com/nikita-volkov/isomorphism-class.git++common language-settings+  default-language: Haskell2010+  default-extensions:+    FlexibleContexts+    FlexibleInstances+    MagicHash+    MultiParamTypeClasses+    NoImplicitPrelude+    ScopedTypeVariables+    TypeApplications+    UndecidableSuperClasses++common library-dependencies+  build-depends:+    base >=4.12 && <5,+    bytestring >=0.10 && <0.12,+    containers >=0.6 && <0.7,+    hashable >=1 && <2,+    primitive >=0.7.3 && <0.8,+    text >=1.2 && <3,+    unordered-containers >=0.2 && <0.3,+    vector >=0.12 && <0.14,++library+  import: language-settings, library-dependencies+  hs-source-dirs: library+  exposed-modules:+    IsomorphismClass+  other-modules:+    IsomorphismClass.Prelude+    IsomorphismClass.TextCompat.Array++test-suite test+  import: language-settings, library-dependencies+  type: exitcode-stdio-1.0+  hs-source-dirs: test+  main-is: Main.hs+  other-modules:+    Test.ExtraInstances+  build-depends:+    bytestring,+    isomorphism-class,+    QuickCheck >=2.13 && <3,+    quickcheck-instances ==0.3.27,+    rebase >=1.15 && <1.16,+    tasty >=1.2.3 && <2,+    tasty-hunit >=0.10.0.2 && <0.11,+    tasty-quickcheck >=0.10.1 && <0.11,
+ library/IsomorphismClass.hs view
@@ -0,0 +1,552 @@+-- |+-- Isomorphism law as a lawful solution to the conversion problem.+--+-- = Conversion problem+--+-- Have you ever looked for a @toString@ function? How often do you+-- import @Data.Text.Lazy@ only to call its 'Data.Text.Lazy.fromStrict'? How+-- about importing @Data.Text@ only to to call its 'Data.Text.unpack'? How+-- about going thru the always fun sequence of+-- importing @Data.ByteString.Builder@ only to to call its+-- 'Data.ByteString.Builder.toLazyByteString' and then importing+-- @Data.ByteString.Lazy@ only to call its 'Data.ByteString.Lazy.toStrict'?+--+-- Those all are instances of one pattern. They are conversions between+-- representations of the same information. Codebases that don't attempt to+-- abstract over this pattern tend to be sprawling with this type of+-- boilerplate. It's noise to the codereader, it's a burden to the+-- implementor and the maintainer.+--+-- = Why another conversion library?+--+-- Many libraries exist that approach the conversion problem. However all of+-- them provide lawless typeclasses leaving it up to the author of the+-- instance to define what makes a proper conversion. This results in+-- inconsistencies across instances and their behaviour being not evident to+-- the user.+--+-- This library tackles this problem with a lawful typeclass, making it+-- evident what any of its instances do.+--+-- = The law+--+-- The key insight of this library is that if you add a requirement for the+-- conversion to be lossless and to have a mirror conversion in the opposite+-- direction, there usually appears to be only one way of defining it. That+-- makes it very clear what the conversion does to the user and how to define+-- it to the author of the conversion.+--+-- That insight itself stems from an observation that almost all of the+-- practical conversions in Haskell share a property: you can restore the+-- original data from its converted form. E.g., you can get a bytestring from+-- a builder and you can create a builder from a bytestring, you can convert+-- a text into a list of chars and vice-versa, bytestring to\/from bytearray,+-- strict bytestring to\/from lazy, list to\/from sequence, sequence to/from+-- vector, set of ints to\/from int-set. In other words, it's always a two-way+-- street with them and there's a lot of instances of this pattern.+--+-- = UX+--+-- A few other accidental findings like encoding this property with recursive+-- typeclass constraints and fine-tuning for the use of+-- the @TypeApplications@ extension resulted in a very terse yet clear API.+--+-- Essentially the whole API is just two functions: 'to' and 'from'. Both+-- perform a conversion between two types. The only difference between them+-- is in what the first type application parameter specifies. E.g.:+--+-- > fromString = from @String+--+-- > toText = to @Text+--+-- In other words 'to' and 'from' let you explicitly specify either the source+-- or the target type of a conversion when you need to help the type+-- inferencer.+--+-- Here are more practical examples:+--+-- @+-- renderNameAndHeight :: 'Text' -> 'Int' -> 'Text'+-- renderNameAndHeight name height =+--   'from' @'TextLazyBuilder.Builder' $+--     "Height of " <> 'to' name <> " is " <> 'showAs' height+-- @+--+-- @+-- combineEncodings :: 'ByteStringShort.ShortByteString' -> 'PrimitiveByteArray.ByteArray' -> 'ByteString' -> [Word8]+-- combineEncodings a b c =+--   'from' @'ByteStringBuilder.Builder' $+--     'to' a <> 'to' b <> 'to' c+-- @+module IsomorphismClass+  ( -- * Typeclass+    IsomorphicTo (..),+    from,++    -- * Common Utilities+    showAs,+  )+where++import qualified Data.ByteString as ByteString+import qualified Data.ByteString.Builder as ByteStringBuilder+import qualified Data.ByteString.Lazy as ByteStringLazy+import qualified Data.ByteString.Short as ByteStringShort+import qualified Data.ByteString.Short.Internal as ByteStringShortInternal+import qualified Data.Primitive.ByteArray as PrimitiveByteArray+import qualified Data.Sequence as Seq+import qualified Data.Set as Set+import qualified Data.Text as Text+import qualified Data.Text.Array as TextArray+import qualified Data.Text.Lazy as TextLazy+import qualified Data.Text.Lazy.Builder as TextLazyBuilder+import qualified Data.Vector as Vector+import qualified Data.Vector.Generic as VectorGeneric+import IsomorphismClass.Prelude+import qualified IsomorphismClass.TextCompat.Array as TextCompatArray++-- | Bidirectional conversion between two types with no loss of information.+-- The bidirectionality is encoded via a recursive dependency with arguments+-- flipped.+--+-- You can read the signature @IsomorphicTo a b@ as \"/B/ is isomorphic to /A/\".+--+-- __Laws__+--+-- /A/ is isomorphic to /B/ if and only if there exists a conversion from /A/+-- to /B/ ('to') and a conversion from /B/ to /A/ ('from') such that:+--+-- - @'from' . 'to' = 'id'@ - For all values of /A/ converting from /A/ to /B/+--     and then converting from /B/ to /A/ produces a value that is identical+--     to the original.+--+-- - @'to' . 'from' = 'id'@ - For all values of /B/ converting from /B/ to /A/+--     and then converting from /A/ to /B/ produces a value that is identical+--     to the original.+--+-- __Usage__+--+-- This class is particularly easy to use in combination with+-- the @TypeApplications@ extension making it clear to the reader what sort+-- of conversion he sees. E.g.,+--+-- > fromString = from @String+--+-- > toText = to @Text+--+-- The types are also self-evident:+--+-- > > :t from @String+-- > from @String :: IsomorphicTo b String => String -> b+--+-- > > :t to @Text+-- > to @Text :: IsomorphicTo Text b => b -> Text+--+-- __Instance Definition__+--+-- For each pair of isomorphic types (/A/ and /B/) the compiler will require+-- you to define two instances, namely: @IsomorphicTo A B@ and @IsomorphicTo+-- B A@.+class IsomorphicTo b a => IsomorphicTo a b where+  to :: b -> a++--++instance IsomorphicTo String Text where+  to = Text.unpack++instance IsomorphicTo String TextLazy.Text where+  to = TextLazy.unpack++instance IsomorphicTo String TextLazyBuilder.Builder where+  to = TextLazy.unpack . TextLazyBuilder.toLazyText++--++instance IsomorphicTo [Word8] ByteString where+  to = ByteString.unpack++instance IsomorphicTo [Word8] ByteStringLazy.ByteString where+  to = ByteStringLazy.unpack++instance IsomorphicTo [Word8] ByteStringShort.ShortByteString where+  to = ByteStringShort.unpack++instance IsomorphicTo [Word8] ByteStringBuilder.Builder where+  to = ByteStringLazy.unpack . ByteStringBuilder.toLazyByteString++instance IsomorphicTo [Word8] PrimitiveByteArray.ByteArray where+  to = toList++instance IsomorphicTo [Word8] TextArray.Array where+  to = to . to @ByteStringShort.ShortByteString++--++instance IsomorphicTo [a] [a] where+  to = id++instance IsomorphicTo [a] (Vector a) where+  to = toList++instance IsomorphicTo [a] (Seq a) where+  to = toList++--++instance IsomorphicTo Text Text where+  to = id++instance IsomorphicTo Text String where+  to = Text.pack++instance IsomorphicTo Text TextLazy.Text where+  to = TextLazy.toStrict++instance IsomorphicTo Text TextLazyBuilder.Builder where+  to = TextLazy.toStrict . TextLazyBuilder.toLazyText++--++instance IsomorphicTo TextLazy.Text TextLazy.Text where+  to = id++instance IsomorphicTo TextLazy.Text String where+  to = TextLazy.pack++instance IsomorphicTo TextLazy.Text Text where+  to = TextLazy.fromStrict++instance IsomorphicTo TextLazy.Text TextLazyBuilder.Builder where+  to = TextLazyBuilder.toLazyText++--++instance IsomorphicTo TextLazyBuilder.Builder TextLazyBuilder.Builder where+  to = id++instance IsomorphicTo TextLazyBuilder.Builder String where+  to = TextLazyBuilder.fromString++instance IsomorphicTo TextLazyBuilder.Builder Text where+  to = TextLazyBuilder.fromText++instance IsomorphicTo TextLazyBuilder.Builder TextLazy.Text where+  to = TextLazyBuilder.fromLazyText++--++instance IsomorphicTo ByteString ByteString where+  to = id++instance IsomorphicTo ByteString [Word8] where+  to = ByteString.pack++instance IsomorphicTo ByteString ByteStringLazy.ByteString where+  to = ByteStringLazy.toStrict++instance IsomorphicTo ByteString ByteStringShort.ShortByteString where+  to = ByteStringShort.fromShort++instance IsomorphicTo ByteString ByteStringBuilder.Builder where+  to = ByteStringLazy.toStrict . ByteStringBuilder.toLazyByteString++instance IsomorphicTo ByteString PrimitiveByteArray.ByteArray where+  to = to . to @ByteStringShort.ShortByteString++instance IsomorphicTo ByteString TextArray.Array where+  to = to . to @ByteStringShort.ShortByteString++--++instance IsomorphicTo ByteStringLazy.ByteString ByteStringLazy.ByteString where+  to = id++instance IsomorphicTo ByteStringLazy.ByteString [Word8] where+  to = ByteStringLazy.pack++instance IsomorphicTo ByteStringLazy.ByteString ByteString where+  to = ByteStringLazy.fromStrict++instance IsomorphicTo ByteStringLazy.ByteString ByteStringShort.ShortByteString where+  to = from @ByteString . to++instance IsomorphicTo ByteStringLazy.ByteString ByteStringBuilder.Builder where+  to = ByteStringBuilder.toLazyByteString++instance IsomorphicTo ByteStringLazy.ByteString PrimitiveByteArray.ByteArray where+  to = to . to @ByteStringShort.ShortByteString++instance IsomorphicTo ByteStringLazy.ByteString TextArray.Array where+  to = to . to @ByteStringShort.ShortByteString++--++instance IsomorphicTo ByteStringShort.ShortByteString ByteStringShort.ShortByteString where+  to = id++instance IsomorphicTo ByteStringShort.ShortByteString [Word8] where+  to = ByteStringShort.pack++instance IsomorphicTo ByteStringShort.ShortByteString ByteString where+  to = ByteStringShort.toShort++instance IsomorphicTo ByteStringShort.ShortByteString ByteStringLazy.ByteString where+  to = to . to @ByteString++instance IsomorphicTo ByteStringShort.ShortByteString ByteStringBuilder.Builder where+  to = to . to @ByteStringLazy.ByteString++instance IsomorphicTo ByteStringShort.ShortByteString PrimitiveByteArray.ByteArray where+  to (PrimitiveByteArray.ByteArray array) = ByteStringShortInternal.SBS array++instance IsomorphicTo ByteStringShort.ShortByteString TextArray.Array where+  to a = ByteStringShortInternal.SBS (TextCompatArray.toUnliftedByteArray a)++--++instance IsomorphicTo ByteStringBuilder.Builder ByteStringBuilder.Builder where+  to = id++instance IsomorphicTo ByteStringBuilder.Builder [Word8] where+  to = to . to @ByteString++instance IsomorphicTo ByteStringBuilder.Builder ByteString where+  to = ByteStringBuilder.byteString++instance IsomorphicTo ByteStringBuilder.Builder ByteStringLazy.ByteString where+  to = ByteStringBuilder.lazyByteString++instance IsomorphicTo ByteStringBuilder.Builder ByteStringShort.ShortByteString where+  to = ByteStringBuilder.shortByteString++instance IsomorphicTo ByteStringBuilder.Builder PrimitiveByteArray.ByteArray where+  to = to . to @ByteStringShort.ShortByteString++instance IsomorphicTo ByteStringBuilder.Builder TextArray.Array where+  to = to . to @ByteStringShort.ShortByteString++--++instance IsomorphicTo PrimitiveByteArray.ByteArray PrimitiveByteArray.ByteArray where+  to = id++instance IsomorphicTo PrimitiveByteArray.ByteArray [Word8] where+  to = fromList++instance IsomorphicTo PrimitiveByteArray.ByteArray ByteStringShort.ShortByteString where+  to (ByteStringShortInternal.SBS array) = PrimitiveByteArray.ByteArray array++instance IsomorphicTo PrimitiveByteArray.ByteArray ByteString where+  to = to . to @ByteStringShort.ShortByteString++instance IsomorphicTo PrimitiveByteArray.ByteArray ByteStringLazy.ByteString where+  to = to . to @ByteStringShort.ShortByteString++instance IsomorphicTo PrimitiveByteArray.ByteArray ByteStringBuilder.Builder where+  to = to . to @ByteStringShort.ShortByteString++instance IsomorphicTo PrimitiveByteArray.ByteArray TextArray.Array where+  to a = PrimitiveByteArray.ByteArray (TextCompatArray.toUnliftedByteArray a)++--++instance IsomorphicTo TextArray.Array [Word8] where+  to = to . to @ByteStringShort.ShortByteString++instance IsomorphicTo TextArray.Array PrimitiveByteArray.ByteArray where+  to (PrimitiveByteArray.ByteArray arr) = TextCompatArray.fromUnliftedByteArray arr++instance IsomorphicTo TextArray.Array ByteStringShort.ShortByteString where+  to (ByteStringShortInternal.SBS arr) = TextCompatArray.fromUnliftedByteArray arr++instance IsomorphicTo TextArray.Array ByteString where+  to = to . to @ByteStringShort.ShortByteString++instance IsomorphicTo TextArray.Array ByteStringLazy.ByteString where+  to = to . to @ByteStringShort.ShortByteString++instance IsomorphicTo TextArray.Array ByteStringBuilder.Builder where+  to = to . to @ByteStringShort.ShortByteString++--++instance IsomorphicTo (Vector a) (Vector a) where+  to = id++instance IsomorphicTo (Vector a) [a] where+  to = Vector.fromList++instance IsomorphicTo (Vector a) (Seq a) where+  to = from @[a] . to++--++instance IsomorphicTo (Seq a) (Seq a) where+  to = id++instance IsomorphicTo (Seq a) [a] where+  to = Seq.fromList++instance IsomorphicTo (Seq a) (Vector a) where+  to = from @[a] . to++--++instance IsomorphicTo (Set a) (Set a) where+  to = id++instance IsomorphicTo (Set Int) IntSet where+  to = fromList . toList++--++instance IsomorphicTo IntSet IntSet where+  to = id++instance IsomorphicTo IntSet (Set Int) where+  to = fromList . toList++--++instance IsomorphicTo (Map k v) (Map k v) where+  to = id++instance IsomorphicTo (Map Int v) (IntMap v) where+  to = fromList . toList++--++instance IsomorphicTo (IntMap a) (IntMap a) where+  to = id++instance IsomorphicTo (IntMap v) (Map Int v) where+  to = fromList . toList++--++instance IsomorphicTo (Maybe a) (Maybe a) where to = id++instance IsomorphicTo (Either a b) (Either a b) where to = id++instance IsomorphicTo (First a) (First a) where to = id++instance IsomorphicTo (Last a) (Last a) where to = id++instance IsomorphicTo (Product a) (Product a) where to = id++instance IsomorphicTo (Sum a) (Sum a) where to = id++--++instance IsomorphicTo Bool Bool where to = id++instance IsomorphicTo Char Char where to = id++instance IsomorphicTo Double Double where to = id++instance IsomorphicTo Float Float where to = id++instance IsomorphicTo Int Int where to = id++instance IsomorphicTo Int Word where to = fromIntegral++instance IsomorphicTo Int16 Int16 where to = id++instance IsomorphicTo Int16 Word16 where to = fromIntegral++instance IsomorphicTo Int32 Int32 where to = id++instance IsomorphicTo Int32 Word32 where to = fromIntegral++instance IsomorphicTo Int64 Int64 where to = id++instance IsomorphicTo Int64 Word64 where to = fromIntegral++instance IsomorphicTo Int8 Int8 where to = id++instance IsomorphicTo Int8 Word8 where to = fromIntegral++instance IsomorphicTo Integer Integer where to = id++instance IsomorphicTo Rational Rational where to = id++instance IsomorphicTo Word Int where to = fromIntegral++instance IsomorphicTo Word Word where to = id++instance IsomorphicTo Word16 Int16 where to = fromIntegral++instance IsomorphicTo Word16 Word16 where to = id++instance IsomorphicTo Word32 Int32 where to = fromIntegral++instance IsomorphicTo Word32 Word32 where to = id++instance IsomorphicTo Word64 Int64 where to = fromIntegral++instance IsomorphicTo Word64 Word64 where to = id++instance IsomorphicTo Word8 Int8 where to = fromIntegral++instance IsomorphicTo Word8 Word8 where to = id++--++-- |+-- 'to' in reverse direction.+--+-- Particularly useful in combination with the @TypeApplications@ extension,+-- where it allows to specify the input type, e.g.:+--+-- > fromString :: IsomorphicTo a String => String -> a+-- > fromString = from @String+--+-- The first type application of the 'to' function on the other hand specifies+-- the output data type.+from :: forall a b. IsomorphicTo b a => a -> b+from = to++-- |+-- Ideally there should be a direct instance and this function+-- should merely serve as a helper for defining instances+-- by merely composing from other instances.+--+-- E.g.,+--+-- > thru @String Proxy+--+-- captures the following pattern:+--+-- > from @String . to+--+-- However it is advised to use the conversion functions directly,+-- since it makes the intent clearer and is actually shorter.+{-# INLINE thru #-}+thru :: (IsomorphicTo a b, IsomorphicTo a c) => Proxy a -> b -> c+thru proxy = from . flip asProxyTypeOf proxy . to++{-# INLINE thruString #-}+thruString :: (IsomorphicTo String a, IsomorphicTo String b) => a -> b+thruString = from @String . to++{-# INLINE thruText #-}+thruText :: (IsomorphicTo Text a, IsomorphicTo Text b) => a -> b+thruText = from @Text . to++{-# INLINE thruList #-}+thruList :: forall a f g. (IsomorphicTo [a] (f a), IsomorphicTo [a] (g a)) => f a -> g a+thruList = from @[a] . to++-- | A utility, which uses the 'Show' instance to produce a value+-- that 'String' is isomorphic to.+--+-- It lets you generalize over the functions like the following:+--+-- > showAsText :: Show a => a -> Text+-- > showAsText = showAs @Text+--+-- > showAsBuilder :: Show a => a -> Builder+-- > showAsBuilder = showAs @Builder+showAs :: forall b a. (IsomorphicTo String b, Show a) => a -> b+showAs = from . show
+ library/IsomorphismClass/Prelude.hs view
@@ -0,0 +1,89 @@+module IsomorphismClass.Prelude+  ( module Exports,+  )+where++import Control.Applicative as Exports+import Control.Arrow as Exports hiding (first, second)+import Control.Category as Exports+import Control.Concurrent as Exports+import Control.Exception as Exports+import Control.Monad as Exports hiding (fail, forM, forM_, mapM, mapM_, msum, sequence, sequence_)+import Control.Monad.Fail as Exports+import Control.Monad.Fix as Exports hiding (fix)+import Control.Monad.IO.Class as Exports+import Control.Monad.ST as Exports+import Data.Bifunctor as Exports+import Data.Bits as Exports+import Data.Bool as Exports+import Data.ByteString as Exports (ByteString)+import Data.Char as Exports+import Data.Coerce as Exports+import Data.Complex as Exports+import Data.Data as Exports+import Data.Dynamic as Exports+import Data.Either as Exports+import Data.Fixed as Exports+import Data.Foldable as Exports hiding (toList)+import Data.Function as Exports hiding (id, (.))+import Data.Functor as Exports+import Data.Functor.Classes as Exports+import Data.Functor.Compose as Exports+import Data.Functor.Contravariant as Exports+import Data.Functor.Identity as Exports+import Data.HashMap.Strict as Exports (HashMap)+import Data.HashSet as Exports (HashSet)+import Data.Hashable as Exports+import Data.IORef as Exports+import Data.Int as Exports+import Data.IntMap.Strict as Exports (IntMap)+import Data.IntSet as Exports (IntSet)+import Data.Ix as Exports+import Data.List as Exports hiding (all, and, any, concat, concatMap, elem, find, foldl, foldl', foldl1, foldr, foldr1, mapAccumL, mapAccumR, maximum, maximumBy, minimum, minimumBy, notElem, or, product, sum)+import Data.List.NonEmpty as Exports (NonEmpty (..))+import Data.Map.Strict as Exports (Map)+import Data.Maybe as Exports+import Data.Monoid as Exports hiding (First (..), Last (..), (<>))+import Data.Ord as Exports+import Data.Proxy as Exports+import Data.Ratio as Exports+import Data.STRef as Exports+import Data.Semigroup as Exports hiding (Option)+import Data.Sequence as Exports (Seq)+import Data.Set as Exports (Set)+import Data.String as Exports+import Data.Text as Exports (Text)+import Data.Traversable as Exports+import Data.Tuple as Exports+import Data.Unique as Exports+import Data.Vector as Exports (Vector)+import Data.Version as Exports+import Data.Void as Exports+import Data.Word as Exports+import Debug.Trace as Exports+import Foreign.ForeignPtr as Exports+import Foreign.Ptr as Exports+import Foreign.StablePtr as Exports+import Foreign.Storable as Exports+import GHC.Conc as Exports hiding (orElse, threadWaitRead, threadWaitReadSTM, threadWaitWrite, threadWaitWriteSTM, withMVar)+import GHC.Exts as Exports (IsList (..), groupWith, inline, lazy, sortWith)+import GHC.Generics as Exports (Generic, Generic1)+import GHC.IO.Exception as Exports+import GHC.OverloadedLabels as Exports+import GHC.Records as Exports+import Numeric as Exports+import Numeric.Natural as Exports+import System.Environment as Exports+import System.Exit as Exports+import System.IO as Exports+import System.IO.Error as Exports+import System.IO.Unsafe as Exports+import System.Mem as Exports+import System.Mem.StableName as Exports+import System.Timeout as Exports+import Text.ParserCombinators.ReadP as Exports (ReadP, ReadS, readP_to_S, readS_to_P)+import Text.ParserCombinators.ReadPrec as Exports (ReadPrec, readP_to_Prec, readPrec_to_P, readPrec_to_S, readS_to_Prec)+import Text.Printf as Exports (hPrintf, printf)+import Text.Read as Exports (Read (..), readEither, readMaybe)+import Unsafe.Coerce as Exports+import Prelude as Exports hiding (all, and, any, concat, concatMap, elem, fail, foldl, foldl1, foldr, foldr1, id, mapM, mapM_, maximum, minimum, notElem, or, product, sequence, sequence_, sum, (.))
+ library/IsomorphismClass/TextCompat/Array.hs view
@@ -0,0 +1,23 @@+{-# LANGUAGE CPP #-}++module IsomorphismClass.TextCompat.Array where++import Data.Text.Array+import GHC.Exts (ByteArray#)+import IsomorphismClass.Prelude++{-# INLINE toUnliftedByteArray #-}+toUnliftedByteArray :: Array -> ByteArray#+#if MIN_VERSION_text(2,0,0)+toUnliftedByteArray (ByteArray a) = a+#else+toUnliftedByteArray (Array a) = a+#endif++{-# INLINE fromUnliftedByteArray #-}+fromUnliftedByteArray :: ByteArray# -> Array+#if MIN_VERSION_text(2,0,0)+fromUnliftedByteArray = ByteArray+#else+fromUnliftedByteArray = Array+#endif
+ test/Main.hs view
@@ -0,0 +1,132 @@+module Main where++import qualified Data.ByteString as ByteString+import qualified Data.ByteString.Builder as ByteStringBuilder+import qualified Data.ByteString.Lazy as ByteStringLazy+import qualified Data.ByteString.Short as ByteStringShort+import qualified Data.Primitive.ByteArray as PrimitiveByteArray+import qualified Data.Sequence as Seq+import qualified Data.Set as Set+import qualified Data.Text as Text+import qualified Data.Text.Lazy as TextLazy+import qualified Data.Text.Lazy.Builder as TextLazyBuilder+import qualified Data.Vector as Vector+import qualified Data.Vector.Generic as VectorGeneric+import IsomorphismClass+import Rebase.Prelude+import Test.ExtraInstances+import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.QuickCheck hiding ((.&.))++main = defaultMain allTests++allTests =+  testGroup "All" $+    [ testPair @String @Text Proxy Proxy,+      testPair @String @TextLazy.Text Proxy Proxy,+      testPair @String @TextLazyBuilder.Builder Proxy Proxy,+      testPair @[Word8] @ByteString Proxy Proxy,+      testPair @[Word8] @ByteStringLazy.ByteString Proxy Proxy,+      testPair @[Word8] @ByteStringShort.ShortByteString Proxy Proxy,+      testPair @[Word8] @ByteStringBuilder.Builder Proxy Proxy,+      testPair @[Word8] @PrimitiveByteArray.ByteArray Proxy Proxy,+      testPair @[Word8] @[Word8] Proxy Proxy,+      testPair @[Word8] @(Vector Word8) Proxy Proxy,+      testPair @[Word8] @(Seq Word8) Proxy Proxy,+      testPair @Text @Text Proxy Proxy,+      testPair @Text @String Proxy Proxy,+      testPair @Text @TextLazy.Text Proxy Proxy,+      testPair @Text @TextLazyBuilder.Builder Proxy Proxy,+      testPair @TextLazy.Text @TextLazy.Text Proxy Proxy,+      testPair @TextLazy.Text @String Proxy Proxy,+      testPair @TextLazy.Text @Text Proxy Proxy,+      testPair @TextLazy.Text @TextLazyBuilder.Builder Proxy Proxy,+      testPair @TextLazyBuilder.Builder @TextLazyBuilder.Builder Proxy Proxy,+      testPair @TextLazyBuilder.Builder @String Proxy Proxy,+      testPair @TextLazyBuilder.Builder @Text Proxy Proxy,+      testPair @TextLazyBuilder.Builder @TextLazy.Text Proxy Proxy,+      testPair @ByteString @ByteString Proxy Proxy,+      testPair @ByteString @[Word8] Proxy Proxy,+      testPair @ByteString @ByteStringLazy.ByteString Proxy Proxy,+      testPair @ByteString @ByteStringShort.ShortByteString Proxy Proxy,+      testPair @ByteString @ByteStringBuilder.Builder Proxy Proxy,+      testPair @ByteString @PrimitiveByteArray.ByteArray Proxy Proxy,+      testPair @ByteStringLazy.ByteString @ByteStringLazy.ByteString Proxy Proxy,+      testPair @ByteStringLazy.ByteString @[Word8] Proxy Proxy,+      testPair @ByteStringLazy.ByteString @ByteString Proxy Proxy,+      testPair @ByteStringLazy.ByteString @ByteStringShort.ShortByteString Proxy Proxy,+      testPair @ByteStringLazy.ByteString @ByteStringBuilder.Builder Proxy Proxy,+      testPair @ByteStringLazy.ByteString @PrimitiveByteArray.ByteArray Proxy Proxy,+      testPair @ByteStringShort.ShortByteString @ByteStringShort.ShortByteString Proxy Proxy,+      testPair @ByteStringShort.ShortByteString @[Word8] Proxy Proxy,+      testPair @ByteStringShort.ShortByteString @ByteString Proxy Proxy,+      testPair @ByteStringShort.ShortByteString @ByteStringLazy.ByteString Proxy Proxy,+      testPair @ByteStringShort.ShortByteString @ByteStringBuilder.Builder Proxy Proxy,+      testPair @ByteStringShort.ShortByteString @PrimitiveByteArray.ByteArray Proxy Proxy,+      testPair @ByteStringBuilder.Builder @ByteStringBuilder.Builder Proxy Proxy,+      testPair @ByteStringBuilder.Builder @[Word8] Proxy Proxy,+      testPair @ByteStringBuilder.Builder @ByteString Proxy Proxy,+      testPair @ByteStringBuilder.Builder @ByteStringLazy.ByteString Proxy Proxy,+      testPair @ByteStringBuilder.Builder @ByteStringShort.ShortByteString Proxy Proxy,+      testPair @ByteStringBuilder.Builder @PrimitiveByteArray.ByteArray Proxy Proxy,+      testPair @PrimitiveByteArray.ByteArray @PrimitiveByteArray.ByteArray Proxy Proxy,+      testPair @PrimitiveByteArray.ByteArray @[Word8] Proxy Proxy,+      testPair @PrimitiveByteArray.ByteArray @ByteStringShort.ShortByteString Proxy Proxy,+      testPair @PrimitiveByteArray.ByteArray @ByteString Proxy Proxy,+      testPair @PrimitiveByteArray.ByteArray @ByteStringLazy.ByteString Proxy Proxy,+      testPair @PrimitiveByteArray.ByteArray @ByteStringBuilder.Builder Proxy Proxy,+      testPair @(Vector Word8) @(Vector Word8) Proxy Proxy,+      testPair @(Vector Word8) @[Word8] Proxy Proxy,+      testPair @(Vector Word8) @(Seq Word8) Proxy Proxy,+      testPair @(Seq Word8) @(Seq Word8) Proxy Proxy,+      testPair @(Seq Word8) @[Word8] Proxy Proxy,+      testPair @(Seq Word8) @(Vector Word8) Proxy Proxy,+      testPair @(Set Word8) @(Set Word8) Proxy Proxy,+      testPair @(Set Int) @IntSet Proxy Proxy,+      testPair @IntSet @IntSet Proxy Proxy,+      testPair @IntSet @(Set Int) Proxy Proxy,+      testPair @(Map Word8 Word8) @(Map Word8 Word8) Proxy Proxy,+      testPair @(Map Int Word8) @(IntMap Word8) Proxy Proxy,+      testPair @(IntMap Word8) @(IntMap Word8) Proxy Proxy,+      testPair @(IntMap Word8) @(Map Int Word8) Proxy Proxy,+      testPair @(Maybe Word8) @(Maybe Word8) Proxy Proxy,+      testPair @(Either Word8 Word8) @(Either Word8 Word8) Proxy Proxy,+      testPair @(First Word8) @(First Word8) Proxy Proxy,+      testPair @(Last Word8) @(Last Word8) Proxy Proxy,+      testPair @(Product Word8) @(Product Word8) Proxy Proxy,+      testPair @(Sum Word8) @(Sum Word8) Proxy Proxy,+      testPair @Bool @Bool Proxy Proxy,+      testPair @Char @Char Proxy Proxy,+      testPair @Double @Double Proxy Proxy,+      testPair @Float @Float Proxy Proxy,+      testPair @Int @Int Proxy Proxy,+      testPair @Int @Word Proxy Proxy,+      testPair @Int16 @Int16 Proxy Proxy,+      testPair @Int16 @Word16 Proxy Proxy,+      testPair @Int32 @Int32 Proxy Proxy,+      testPair @Int32 @Word32 Proxy Proxy,+      testPair @Int64 @Int64 Proxy Proxy,+      testPair @Int64 @Word64 Proxy Proxy,+      testPair @Int8 @Int8 Proxy Proxy,+      testPair @Int8 @Word8 Proxy Proxy,+      testPair @Integer @Integer Proxy Proxy,+      testPair @Rational @Rational Proxy Proxy,+      testPair @Word @Int Proxy Proxy,+      testPair @Word @Word Proxy Proxy,+      testPair @Word16 @Int16 Proxy Proxy,+      testPair @Word16 @Word16 Proxy Proxy,+      testPair @Word32 @Int32 Proxy Proxy,+      testPair @Word32 @Word32 Proxy Proxy,+      testPair @Word64 @Int64 Proxy Proxy,+      testPair @Word64 @Word64 Proxy Proxy,+      testPair @Word8 @Int8 Proxy Proxy,+      testPair @Word8 @Word8 Proxy Proxy+    ]++testPair :: forall a b. (IsomorphicTo a b, Eq a, Arbitrary a, Show a, Typeable a, Typeable b) => Proxy a -> Proxy b -> TestTree+testPair _ _ =+  testProperty name $ \a ->+    a === from @b (from @a a)+  where+    name = show (typeOf (undefined :: a)) <> "/" <> show (typeOf (undefined :: b))
+ test/Test/ExtraInstances.hs view
@@ -0,0 +1,46 @@+module Test.ExtraInstances () where++import qualified Data.ByteString as ByteString+import qualified Data.ByteString.Builder as ByteStringBuilder+import qualified Data.ByteString.Lazy as ByteStringLazy+import qualified Data.ByteString.Short as ByteStringShort+import qualified Data.HashSet as HashSet+import qualified Data.Primitive.ByteArray as PrimitiveByteArray+import qualified Data.Sequence as Seq+import qualified Data.Set as Set+import qualified Data.Text as Text+import qualified Data.Text.Lazy as TextLazy+import qualified Data.Text.Lazy.Builder as TextLazyBuilder+import qualified Data.Vector as Vector+import qualified Data.Vector.Generic as VectorGeneric+import qualified Data.Vector.Primitive as VectorPrimitive+import qualified Data.Vector.Storable as VectorStorable+import qualified Data.Vector.Unboxed as VectorUnboxed+import Rebase.Prelude+import Test.QuickCheck+import Test.QuickCheck.Instances++instance (Arbitrary a, VectorPrimitive.Prim a, Show a) => Arbitrary (VectorPrimitive.Vector a) where+  arbitrary = arbitraryVector+  shrink = shrinkVector++instance Arbitrary PrimitiveByteArray.ByteArray where+  arbitrary = fromList <$> arbitrary+  shrink = fmap fromList . shrink . toList++instance Arbitrary TextLazyBuilder.Builder where+  arbitrary = TextLazyBuilder.fromText <$> arbitrary+  shrink = shrinkMap TextLazyBuilder.fromLazyText TextLazyBuilder.toLazyText++instance Eq ByteStringBuilder.Builder where+  (==) = on (==) ByteStringBuilder.toLazyByteString++instance Arbitrary ByteStringBuilder.Builder where+  arbitrary = ByteStringBuilder.byteString <$> arbitrary+  shrink = shrinkMap ByteStringBuilder.lazyByteString ByteStringBuilder.toLazyByteString++arbitraryVector :: (VectorGeneric.Vector v a, Arbitrary a, Show a) => Gen (v a)+arbitraryVector = VectorGeneric.fromList <$> arbitrary++shrinkVector :: (VectorGeneric.Vector v a, Arbitrary a) => v a -> [v a]+shrinkVector = fmap VectorGeneric.fromList . shrink . VectorGeneric.toList