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 +22/−0
- isomorphism-class.cabal +65/−0
- library/IsomorphismClass.hs +552/−0
- library/IsomorphismClass/Prelude.hs +89/−0
- library/IsomorphismClass/TextCompat/Array.hs +23/−0
- test/Main.hs +132/−0
- test/Test/ExtraInstances.hs +46/−0
+ 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