intro 0.1.0.10 → 0.9.0.0
raw patch · 11 files changed
Files
- LICENSE +1/−1
- README.md +9/−9
- intro.cabal +41/−60
- src/Intro.hs +99/−109
- src/Intro/ConvertIntegral.hs +79/−0
- src/Intro/ConvertString.hs +171/−0
- src/Intro/Trustworthy.hs +21/−21
- test/BaseCompat.hs +2/−6
- test/OpticsCompat.hs +7/−0
- test/compat.hs +0/−9
- test/test.hs +74/−0
LICENSE view
@@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016 Daniel Mendler+Copyright (c) 2016-2017 Daniel Mendler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal
README.md view
@@ -1,4 +1,4 @@-# Intro: My current Haskell Prelude+# Intro: Safe and minimal Haskell Prelude [](https://hackage.haskell.org/package/intro) [](http://travis-ci.org/minad/intro)@@ -9,22 +9,22 @@ For String overloading the extension 'OverloadedStrings' should be used. Container types and Monad transformers are provided. -Most important - this Prelude tries to keep things simple.+Most important - this Prelude tries to keep things simple and minimal. This means it just reexports from base and commonly used libraries and adds only very few additional functions. List of design decisions: -* Keep everything at one place (There are one two modules and Intro.Trustworthy is only there for Safe Haskell)+* Keep everything at one place * Conservative extension over the base Prelude-* Rely only on very common external libraries+* Rely only on common additional libraries * Avoid writing custom functions-* Export everything explicitly to provide a stable interface and for good documentation+* Export everything explicitly to provide a stable interface and good documentation * Export only total functions or provide safe alternatives (Very few exceptions like div etc.)-* Prefer Text over String, provide ConvertibleStrings-* Provide Monad transformers+* Prefer Text over String, provide ConvertString and EncodeString+* Provide monad transformers * Provide container types * Prefer generic functions * Debugging functions, like 'Intro.Trustworthy.trace' and 'undefined' are available but produce compile time warnings-* Don't provide error, only panic instead-* Compatibility with Control.Lens+* Replace error with panic+* Compatibility with unqualified import of Control.Lens and Optics
intro.cabal view
@@ -1,10 +1,7 @@--- This file has been generated from package.yaml by hpack version 0.15.0.------ see: https://github.com/sol/hpack-+cabal-version: 1.12 name: intro-version: 0.1.0.10-synopsis: "Fixed Prelude" - Mostly total and safe, provides Text and Monad transformers+version: 0.9.0.0+synopsis: Safe and minimal prelude description: Intro is a modern Prelude which provides safe alternatives for most of the partial functions and follows other best practices, e.g., Text is preferred over String.@@ -22,13 +19,11 @@ bug-reports: https://github.com/minad/intro/issues author: Daniel Mendler <mail@daniel-mendler.de> maintainer: Daniel Mendler <mail@daniel-mendler.de>-copyright: 2016 Daniel Mendler+copyright: 2016-2017 Daniel Mendler license: MIT license-file: LICENSE-tested-with: GHC == 7.10.3, GHC == 8.0.1+tested-with: GHC == 8.6.5, GHC == 8.8.1, GHC == 8.10.1 build-type: Simple-cabal-version: >= 1.10- extra-source-files: README.md @@ -37,67 +32,53 @@ location: https://github.com/minad/intro library- hs-source-dirs:- src- ghc-options: -Wall- build-depends:- base >= 4.8 && < 5.0- , bifunctors >= 5.2 && < 5.5- , binary >= 0.7 && < 0.9- , bytestring >= 0.9 && < 0.11- , containers >= 0.5 && < 0.6- , deepseq >= 1.4 && < 1.5- , dlist >= 0.7 && < 0.9- , extra >= 1.5.1 && < 1.6- , hashable >= 1.2.5 && < 1.3- , mtl >= 2.2 && < 2.3- , safe >= 0.3.11 && < 0.4- , string-conversions >= 0.4 && < 0.5- , tagged >= 0.8 && < 0.9- , text >= 0.7 && < 1.3- , transformers >= 0.4 && < 0.6- , unordered-containers >= 0.2 && < 0.3- , writer-cps-mtl >= 0.1.1.2 && < 0.2- if impl(ghc < 8.0)- build-depends:- semigroups >= 0.9 && < 1 exposed-modules: Intro other-modules:+ Intro.ConvertString+ Intro.ConvertIntegral Intro.Trustworthy- Paths_intro+ hs-source-dirs:+ src+ ghc-options: -Wall+ build-depends:+ base >=4.8 && <5.0+ , bytestring >=0.9 && <0.11+ , containers >=0.5 && <0.7+ , extra >=1.5.1 && <2.0+ , hashable >=1.2.5 && <2.0+ , mtl >=2.2 && <2.3+ , safe >=0.3.18 && <0.4+ , text >=0.7 && <1.3+ , transformers >=0.4 && <0.6+ , unordered-containers >=0.2 && <0.3+ , writer-cps-mtl >=0.1.1.2 && <0.2 default-language: Haskell2010 -test-suite compat+test-suite test type: exitcode-stdio-1.0- main-is: compat.hs+ main-is: test.hs+ other-modules:+ BaseCompat+ LensCompat+ OpticsCompat hs-source-dirs: test ghc-options: -Wall build-depends:- base >= 4.8 && < 5.0- , bifunctors >= 5.2 && < 5.5- , binary >= 0.7 && < 0.9- , bytestring >= 0.9 && < 0.11- , containers >= 0.5 && < 0.6- , deepseq >= 1.4 && < 1.5- , dlist >= 0.7 && < 0.9- , extra >= 1.5.1 && < 1.6- , hashable >= 1.2.5 && < 1.3- , mtl >= 2.2 && < 2.3- , safe >= 0.3.11 && < 0.4- , string-conversions >= 0.4 && < 0.5- , tagged >= 0.8 && < 0.9- , text >= 0.7 && < 1.3- , transformers >= 0.4 && < 0.6- , unordered-containers >= 0.2 && < 0.3- , writer-cps-mtl >= 0.1.1.2 && < 0.2+ QuickCheck+ , base+ , bytestring+ , containers+ , extra+ , hashable , intro , lens- if impl(ghc < 8.0)- build-depends:- semigroups >= 0.9 && < 1- other-modules:- BaseCompat- LensCompat+ , optics+ , mtl+ , safe+ , text+ , transformers+ , unordered-containers+ , writer-cps-mtl default-language: Haskell2010
src/Intro.hs view
@@ -1,5 +1,4 @@ {-# OPTIONS_HADDOCK show-extensions #-}-{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-}@@ -9,7 +8,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Intro--- Copyright : (c) Daniel Mendler 2016+-- Copyright : (c) Daniel Mendler 2016-2017 -- License : MIT -- -- Maintainer : mail@daniel-mendler.de@@ -28,19 +27,19 @@ -- -- List of design decisions: ----- * Keep everything at one place (There are one two modules and Intro.Trustworthy is only there for Safe Haskell)+-- * Keep everything at one place (There are only three modules and Intro.Trustworthy is only there for Safe Haskell) -- * Conservative extension over the base Prelude -- * Rely only on very common external libraries -- * Avoid writing custom functions -- * Export everything explicitly to provide a stable interface and for good documentation -- * Export only total functions or provide safe alternatives (Very few exceptions like div etc.)--- * Prefer Text over String, provide ConvertibleStrings+-- * Prefer Text over String, provide 'ConvertString' and 'EncodeString' -- * Provide Monad transformers -- * Provide container types -- * Prefer generic functions--- * Debugging functions, like 'Intro.Trustworthy.trace' and 'undefined' are available but produce compile time warnings+-- * Debugging functions, like 'trace' and 'undefined' are available but produce compile time warnings -- * Don't provide error, only panic instead--- * Compatibility with Control.Lens+-- * Compatibility with unqualified import of Control.Lens -- -- Some 'Prelude' functions are missing from 'Intro'. More general variants are available for the following functions: --@@ -54,13 +53,26 @@ -- * 'sequence' = 'Control.Applicative.sequenceA' -- * 'sequence_' = 'Control.Applicative.sequenceA_' ----- Unsafe functions are not provided. Use the '*May' or '*Def' alternatives instead.+-- Integral type conversions are more restricted: ----- * 'cycle', 'head', 'tail', 'init', 'last'--- * 'foldl1', 'foldr1', 'maximum', 'minimum'--- * 'toEnum', 'pred', 'succ'--- * 'read' is replaced by 'readMaybe'+-- * 'toIntegral' is a safer, but more restricted version of 'fromIntegral'+-- * 'toIntegerSized' is safe and checked+-- * 'fromIntegralUnsafe' to get the unsafe, overflowing behavior+-- * 'fromIntegerUnsafe' instead of 'fromInteger' --+-- Unsafe functions are not provided. For example 'read' is replaced by 'readMaybe'.+-- The unsafe list functions are replaced by their 'NonEmpty' counterparts. Furthermore '*May' and '*Def'+-- functions are exported from the 'safe' package, e.g., 'headMay'.+--+-- * 'cycleMay', 'headMay', 'tailMay', 'initMay', 'lastMay'+-- * 'toEnumMay', 'predMay', 'succMay'+--+-- The 'maximum' and 'minimum' functions have been replaced by variants which+-- are safe for empty structures.+--+-- * 'maximumBound', 'maximumBounded', ...+-- * 'minimumBound', 'minimumBounded', ...+-- -- These functions are not provided for various reasons: -- -- * '!!' is unsafe and /O(n)/. Use a 'Data.Map.Map' instead.@@ -70,15 +82,16 @@ -- * 'gcd' and 'lcm' are not commonly used. -- * 'error' and 'errorWithoutStackTrace' are not provided. Use 'panic' instead. -- * 'ioError' and 'userError' are not provided. Import modules for exception handling separately if needed.--- * Some 'Read' and 'Show' class functions are not provided. Don't write these instances yourself.+-- * Some 'Text.Read.Read' and 'Show' class functions are not provided. Don't write these instances yourself. -- -- Additional types and functions: -- -- * 'LText' alias for lazy 'Text' -- * 'LByteString' alias for lazy 'ByteString' -- * 'fromFoldable' to convert from 'Data.Foldable.Foldable' to an 'IsList' type--- * 'convertList' to convert between two 'IsList' types. This function can be used instead of the 'toList' function--- originally provided by the 'IsList' class.+-- * 'convertList' to convert between two 'IsList' types.+-- * 'asList' to convert from an 'IsList' type to a 'List'. This function is an+-- alias for the 'toList' function from the 'IsList' class. -- * 'showT' and 'showS' are monomorphic 'show' functions. -- * '<>^' lifted composition -- * '.:' function composition@@ -132,8 +145,9 @@ , Intro.Trustworthy.IsList( Item , fromList- -- , toList -- provided by Foldable+ -- , toList -- renamed to asList )+ , asList , convertList , fromFoldable , Data.List.break@@ -156,6 +170,7 @@ , Data.List.isPrefixOf , Data.List.isSuffixOf , Data.List.iterate+ , Data.List.iterate' , Data.List.lookup , Data.List.Extra.nubOrd , Data.List.Extra.nubOrdBy@@ -179,6 +194,7 @@ , Data.List.take , Data.List.Extra.takeEnd , Data.List.takeWhile+ , Data.List.Extra.takeWhileEnd , Data.List.transpose , Data.List.unfoldr , Data.List.unzip@@ -187,7 +203,6 @@ , Data.List.zip3 , Data.List.zipWith , Data.List.zipWith3- -- , Data.List.cycle -- partial , Safe.headDef , Safe.headMay -- prefer pattern match , Safe.initDef@@ -204,6 +219,11 @@ -- (<|), -- in lens , Data.List.NonEmpty.scanl1 , Data.List.NonEmpty.scanr1+ , Data.List.NonEmpty.head+ , Data.List.NonEmpty.init+ , Data.List.NonEmpty.last+ , Data.List.NonEmpty.tail+ , Data.List.NonEmpty.cycle -- ** Tuple , Data.Tuple.fst@@ -242,10 +262,13 @@ -- ** ByteString , Data.ByteString.ByteString , LByteString+ , Data.ByteString.Short.ShortByteString - -- ** Conversion+ -- ** String conversion , Data.String.IsString(fromString)- , Data.String.Conversions.ConvertibleStrings(convertString)+ , Intro.ConvertString.ConvertString(convertString)+ , Intro.ConvertString.EncodeString(encodeString, decodeString, decodeStringLenient)+ , Lenient(..) -- * Container types @@ -265,9 +288,6 @@ -- ** Seq , Data.Sequence.Seq - -- ** DList- , Intro.Trustworthy.DList- -- * Numeric types -- ** Big integers@@ -290,18 +310,12 @@ , Prelude.Float , Prelude.Double - -- ** Rational- , Data.Ratio.Ratio- , Data.Ratio.Rational- , (Data.Ratio.%)- , Data.Ratio.numerator- , Data.Ratio.denominator- , Data.Ratio.approxRational- -- * Numeric type classes -- ** Num- , Prelude.Num((+), (-), (*), negate, abs, signum, fromInteger)+ , Prelude.Num((+), (-), (*), negate, abs, signum+ -- fromInteger+ ) , Prelude.subtract , (Prelude.^) -- partial functions! @@ -311,7 +325,11 @@ -- ** Integral , Prelude.Integral(quot, rem, div, mod, quotRem, divMod, toInteger) -- partial functions!- , Prelude.fromIntegral+ , Intro.ConvertIntegral.ToIntegral(..)+ , Data.Bits.toIntegralSized+ , Intro.ConvertIntegral.fromIntegralUnsafe+ , Intro.ConvertIntegral.fromIntegerUnsafe+ --, Prelude.fromIntegral , Prelude.even , Prelude.odd --, Prelude.gcd@@ -347,37 +365,29 @@ -- ** Show , Text.Show.Show-#if MIN_VERSION_base(4,9,0) , Data.Functor.Classes.Show1 , Data.Functor.Classes.Show2-#endif , show , showT , showS -- ** Read , Text.Read.Read-#if MIN_VERSION_base(4,9,0) , Data.Functor.Classes.Read1 , Data.Functor.Classes.Read2-#endif , readMaybe - -- * Equality and Ordering+ -- * Equality and ordering -- ** Eq , Data.Eq.Eq((==), (/=))-#if MIN_VERSION_base(4,9,0) , Data.Functor.Classes.Eq1 , Data.Functor.Classes.Eq2-#endif -- ** Ord , Data.Ord.Ord(compare, (<), (>), (<=), (>=), max, min)-#if MIN_VERSION_base(4,9,0) , Data.Functor.Classes.Ord1 , Data.Functor.Classes.Ord2-#endif , Data.Ord.Ordering(LT,GT,EQ) , Data.Ord.Down(Down) , Data.Ord.comparing@@ -432,11 +442,21 @@ ) , (Data.Functor.$>) , (Data.Functor.<$>)+ , (Data.Functor.<&>) , map , Data.Functor.void , Control.Applicative.Const(Const, getConst) -- Data.Functor.Const , Data.Functor.Identity.Identity(Identity, runIdentity) + -- ** Contravariant+ , Data.Functor.Contravariant.Contravariant(+ (>$),+ contramap+ )+ , (Data.Functor.Contravariant.$<)+ , (Data.Functor.Contravariant.>$<)+ , (Data.Functor.Contravariant.>$$<)+ -- ** Foldable , Data.Foldable.Foldable(elem, fold, foldMap, foldr, foldr',@@ -459,17 +479,17 @@ , Data.Foldable.notElem , Data.Foldable.sequenceA_ , Safe.Foldable.foldl1May- , Safe.Foldable.foldl1Def , Safe.Foldable.foldr1May- , Safe.Foldable.foldr1Def , Safe.Foldable.maximumByMay- , Safe.Foldable.maximumByDef+ , Safe.Foldable.maximumBoundBy , Safe.Foldable.minimumByMay- , Safe.Foldable.minimumByDef+ , Safe.Foldable.minimumBoundBy , Safe.Foldable.maximumMay- , Safe.Foldable.maximumDef+ , Safe.Foldable.maximumBounded+ , Safe.Foldable.maximumBound , Safe.Foldable.minimumMay- , Safe.Foldable.minimumDef+ , Safe.Foldable.minimumBounded+ , Safe.Foldable.minimumBound -- ** Traversable , Data.Traversable.Traversable(traverse, sequenceA)@@ -493,15 +513,10 @@ -- ** Monad , Control.Monad.Monad((>>=))-#if MIN_VERSION_base(4,9,0)- , Control.Monad.Fail.MonadFail-#endif- , fail , Control.Monad.Fix.MonadFix(mfix) , (Control.Monad.=<<) , (Control.Monad.<=<) , (Control.Monad.>=>)- , Control.Monad.MonadPlus(mzero, mplus) , Control.Monad.join , Control.Monad.guard , Control.Monad.when@@ -538,10 +553,11 @@ , Data.Bitraversable.bifor , Data.Bitraversable.bisequenceA - -- * Monad transformer+ -- * Effects and monad transformers , Control.Monad.Trans.MonadTrans(lift) - -- ** MaybeT+ -- ** MonadPlus and MaybeT+ , Control.Monad.MonadPlus , Control.Monad.Trans.Maybe.MaybeT(MaybeT, runMaybeT) , Control.Monad.Trans.Maybe.mapMaybeT @@ -615,26 +631,19 @@ , GHC.Generics.Generic , GHC.Generics.Generic1 , Data.Typeable.Typeable- , Control.DeepSeq.NFData- , Data.Binary.Binary -- * Type level-#if MIN_VERSION_base(4,9,0) , Data.Kind.Type-#endif , Intro.Trustworthy.Constraint , Data.Proxy.Proxy(Proxy)- , Data.Tagged.Tagged(Tagged)- , Data.Tagged.unTagged+ --, Data.Tagged.Tagged(Tagged)+ --, Data.Tagged.unTagged -- * IO , System.IO.IO , Control.Monad.Trans.MonadIO(liftIO) -- ** Console- , getChar- , getContents- , getLine , print , putChar , putStr@@ -650,13 +659,18 @@ , writeFileUtf8 , appendFileUtf8 - -- * Error and Debugging+ -- * Error handling and debugging+ , HasCallStack+ , Control.Monad.Fail.MonadFail+ , fail , panic , undefined , Intro.Trustworthy.trace , Intro.Trustworthy.traceIO+ , Intro.Trustworthy.traceId , Intro.Trustworthy.traceM , Intro.Trustworthy.traceShow+ , Intro.Trustworthy.traceShowId , Intro.Trustworthy.traceShowM ) where @@ -668,18 +682,18 @@ import Data.Maybe (Maybe, fromMaybe) import Data.Semigroup (Semigroup((<>))) import Data.String (IsString(fromString), String)-import Data.String.Conversions (ConvertibleStrings(convertString)) import Data.Text (Text)-import Intro.Trustworthy (HasCallStack, IsList(Item, toList, fromList))+import Intro.ConvertIntegral+import Intro.ConvertString+import Intro.Trustworthy import System.IO (FilePath)-import Text.Read (Read) import Text.Show (Show) import qualified Control.Applicative import qualified Control.Category-import qualified Control.DeepSeq import qualified Control.Monad import qualified Control.Monad.Except import qualified Control.Monad.Extra+import qualified Control.Monad.Fail import qualified Control.Monad.Fix import qualified Control.Monad.RWS.CPS import qualified Control.Monad.Reader@@ -689,25 +703,28 @@ import qualified Control.Monad.Writer.CPS import qualified Data.Bifoldable import qualified Data.Bifunctor-import qualified Data.Binary import qualified Data.Bitraversable import qualified Data.Bits import qualified Data.Bool import qualified Data.ByteString import qualified Data.ByteString.Lazy+import qualified Data.ByteString.Short import qualified Data.Either import qualified Data.Either.Extra import qualified Data.Eq import qualified Data.Foldable import qualified Data.Function import qualified Data.Functor+import qualified Data.Functor.Classes import qualified Data.Functor.Identity+import qualified Data.Functor.Contravariant import qualified Data.HashMap.Strict import qualified Data.HashSet import qualified Data.Hashable import qualified Data.Int import qualified Data.IntMap import qualified Data.IntSet+import qualified Data.Kind import qualified Data.List import qualified Data.List.Extra import qualified Data.List.NonEmpty@@ -716,11 +733,9 @@ import qualified Data.Monoid import qualified Data.Ord import qualified Data.Proxy-import qualified Data.Ratio import qualified Data.Semigroup import qualified Data.Sequence import qualified Data.Set-import qualified Data.Tagged import qualified Data.Text.IO import qualified Data.Text.Lazy import qualified Data.Traversable@@ -729,7 +744,6 @@ import qualified Data.Void import qualified Data.Word import qualified GHC.Generics-import qualified Intro.Trustworthy import qualified Numeric.Natural import qualified Prelude import qualified Safe@@ -738,12 +752,6 @@ import qualified Text.Read import qualified Text.Show -#if MIN_VERSION_base(4,9,0)-import qualified Control.Monad.Fail-import qualified Data.Functor.Classes-import qualified Data.Kind-#endif- -- | Alias for lazy 'Data.Text.Lazy.Text' type LText = Data.Text.Lazy.Text @@ -762,6 +770,12 @@ convertList = fromList . toList {-# INLINE convertList #-} +-- | The 'asList' function extracts a list of @Item a@ from the structure @a@.+-- It should satisfy fromList . asList = id.+asList :: (IsList a) => a -> [Item a]+asList = Intro.Trustworthy.toList+{-# INLINE asList #-}+ -- | A synonym for 'fmap'. -- -- @map = 'fmap'@@@ -769,9 +783,9 @@ map = fmap {-# INLINE map #-} --- | Convert a value to a readable string type supported by 'ConvertibleStrings' using the 'Show' instance.-show :: (Show a, IsString s) => a -> s-show = fromString . showS+-- | Convert a value to a readable string type supported by 'ConvertString' using the 'Show' instance.+show :: (Show a, ConvertString String s) => a -> s+show = convertString . showS {-# INLINE show #-} -- | Convert a value to a readable 'Text' using the 'Show' instance.@@ -786,7 +800,7 @@ -- | Parse a string type using the 'Text.Read.Read' instance. -- Succeeds if there is exactly one valid result.-readMaybe :: (Text.Read.Read b, ConvertibleStrings a String) => a -> Maybe b+readMaybe :: (Text.Read.Read b, ConvertString a String) => a -> Maybe b readMaybe = Text.Read.readMaybe . convertString {-# INLINE readMaybe #-} @@ -806,27 +820,6 @@ print = liftIO . System.IO.print {-# INLINE print #-} --- | The 'getContents' operation returns all user input as a strict 'Text'.------ __Note__: This function is lifted to the 'MonadIO' class.-getContents :: MonadIO m => m Text-getContents = liftIO Data.Text.IO.getContents-{-# INLINE getContents #-}---- | Read a line from the standard input device as a strict 'Text'.------ __Note__: This function is lifted to the 'MonadIO' class.-getLine :: MonadIO m => m Text-getLine = liftIO Data.Text.IO.getLine-{-# INLINE getLine #-}---- | Read a character from the standard input device.------ __Note__: This function is lifted to the 'MonadIO' class.-getChar :: MonadIO m => m Char-getChar = liftIO System.IO.getChar-{-# INLINE getChar #-}- -- | Write a strict 'Text' to the standard output device. -- -- __Note__: This function is lifted to the 'MonadIO' class.@@ -870,10 +863,12 @@ {-# INLINE appendFile #-} -- | Read an entire file strictly into a 'Text' using UTF-8 encoding.+-- The decoding is done using 'decodeStringLenient'. Invalid characters are replaced+-- by the Unicode replacement character '\FFFD'. -- -- __Note__: This function is lifted to the 'MonadIO' class. readFileUtf8 :: MonadIO m => FilePath -> m Text-readFileUtf8 = map convertString . readFile+readFileUtf8 = map decodeStringLenient . readFile {-# INLINE readFileUtf8 #-} -- | Write a 'Text' to a file using UTF-8 encoding.@@ -893,7 +888,7 @@ -- | Throw an undefined error. Use only for debugging. undefined :: HasCallStack => a undefined = Prelude.undefined-{-# WARNING undefined "'undefined' remains in code" #-}+{-# WARNING undefined "'undefined' should be used only for debugging" #-} -- | '<>' lifted to 'Control.Applicative.Applicative' (<>^) :: (Control.Applicative.Applicative f, Semigroup a) => f a -> f a -> f a@@ -956,11 +951,6 @@ -- @ -- fail _ = mzero -- @-#if MIN_VERSION_base(4,9,0) fail :: Control.Monad.Fail.MonadFail m => Text -> m a fail = Control.Monad.Fail.fail . convertString-#else-fail :: Control.Monad.Monad m => Text -> m a-fail = Control.Monad.fail . convertString-#endif {-# INLINE fail #-}
+ src/Intro/ConvertIntegral.hs view
@@ -0,0 +1,79 @@+-----------------------------------------------------------------------------+-- |+-- Module : Intro.ConvertInt+-- Copyright : (c) Daniel Mendler 2020+-- License : MIT+--+-- Maintainer : mail@daniel-mendler.de+-- Stability : experimental+-- Portability : portable+--+-- Integer conversion+--+-----------------------------------------------------------------------------++{-# LANGUAGE Safe #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE DefaultSignatures #-}++module Intro.ConvertIntegral (+ ToIntegral(..)+ , fromIntegralUnsafe+ , fromIntegerUnsafe+) where++import Data.Int+import Data.Word++class ToIntegral a b where+ toIntegral :: a -> b+ default toIntegral :: (Integral a, Integral b) => a -> b+ toIntegral = fromIntegral+ {-# INLINE toIntegral #-}++instance ToIntegral Word8 Int16+instance ToIntegral Word8 Int32+instance ToIntegral Word8 Int64+instance ToIntegral Word8 Int+instance ToIntegral Word16 Int32+instance ToIntegral Word16 Int64+instance ToIntegral Word16 Int+instance ToIntegral Word32 Int64++instance ToIntegral Word8 Word16+instance ToIntegral Word8 Word32+instance ToIntegral Word8 Word64+instance ToIntegral Word8 Word+instance ToIntegral Word16 Word32+instance ToIntegral Word16 Word64+instance ToIntegral Word16 Word+instance ToIntegral Word32 Word64++instance ToIntegral Int8 Integer+instance ToIntegral Int16 Integer+instance ToIntegral Int32 Integer+instance ToIntegral Int64 Integer+instance ToIntegral Int Integer++instance ToIntegral Word8 Integer+instance ToIntegral Word16 Integer+instance ToIntegral Word32 Integer+instance ToIntegral Word64 Integer+instance ToIntegral Word Integer++instance ToIntegral Int8 Int16+instance ToIntegral Int8 Int32+instance ToIntegral Int8 Int64+instance ToIntegral Int8 Int+instance ToIntegral Int16 Int32+instance ToIntegral Int16 Int64+instance ToIntegral Int16 Int+instance ToIntegral Int32 Int64++fromIntegralUnsafe :: (Integral a, Num b) => a -> b+fromIntegralUnsafe = fromIntegral+{-# INLINE fromIntegralUnsafe #-}++fromIntegerUnsafe :: Num a => Integer -> a+fromIntegerUnsafe = fromInteger+{-# INLINE fromIntegerUnsafe #-}
+ src/Intro/ConvertString.hs view
@@ -0,0 +1,171 @@+-----------------------------------------------------------------------------+-- |+-- Module : Intro.ConvertString+-- Copyright : (c) Daniel Mendler 2017+-- License : MIT+--+-- Maintainer : mail@daniel-mendler.de+-- Stability : experimental+-- Portability : portable+--+-- String conversion and decoding+--+-----------------------------------------------------------------------------++{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE Safe #-}++module Intro.ConvertString (+ ConvertString(..)+ , EncodeString(..)+ , Lenient(..)+) where++import Data.ByteString (ByteString)+import Data.ByteString.Short (ShortByteString)+import Data.Either.Extra (eitherToMaybe)+import Data.Eq (Eq)+import Data.Foldable (Foldable)+import Data.Function (id, (.))+import Data.Functor (Functor(fmap))+import Data.Maybe (Maybe)+import Data.Ord (Ord)+import Data.String (String)+import Data.Text (Text)+import Data.Text.Encoding.Error (lenientDecode)+import Data.Traversable (Traversable)+import Data.Word (Word8)+import GHC.Generics (Generic, Generic1)+import Text.Read (Read)+import Text.Show (Show)+import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString.Short as S+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Encoding as TLE++-- | Conversion of strings to other string types+--+-- @+-- ('convertString' :: b -> a) . ('convertString' :: a -> b) ≡ ('id' :: a -> a)+-- ('convertString' :: b -> 'Maybe' a) . ('convertString' :: a -> b) ≡ ('Just' :: a -> 'Maybe' a)+-- ('convertString' :: b -> 'Lenient' a) . ('convertString' :: a -> b) ≡ ('Lenient' :: a -> 'Lenient' a)+-- @+class ConvertString a b where+ -- | Convert a string to another string type+ convertString :: a -> b++-- | Encode and decode strings as a byte sequence+--+-- @+-- 'decodeString' . 'encodeString' ≡ 'Just'+-- 'decodeStringLenient' . 'encodeString' ≡ 'id'+-- @+class (ConvertString a b, ConvertString b (Maybe a), ConvertString b (Lenient a)) => EncodeString a b where+ -- | Encode a string as a byte sequence+ encodeString :: a -> b+ encodeString = convertString+ {-# INLINE encodeString #-}++ -- | Lenient decoding of byte sequence+ --+ -- Lenient means that invalid characters are replaced+ -- by the Unicode replacement character '\FFFD'.+ decodeStringLenient :: b -> a+ decodeStringLenient = getLenient . convertString+ {-# INLINE decodeStringLenient #-}++ -- | Decode byte sequence+ --+ -- If the decoding fails, return Nothing.+ decodeString :: b -> Maybe a+ decodeString = convertString+ {-# INLINE decodeString #-}++-- | Newtype wrapper for a string which was decoded leniently.+newtype Lenient a = Lenient { getLenient :: a }+ deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable, Generic, Generic1)++instance ConvertString BL.ByteString (Lenient String) where {-# INLINE convertString #-}; convertString = Lenient . TL.unpack . TLE.decodeUtf8With lenientDecode+instance ConvertString BL.ByteString (Lenient TL.Text) where {-# INLINE convertString #-}; convertString = Lenient . TLE.decodeUtf8With lenientDecode+instance ConvertString BL.ByteString (Lenient Text) where {-# INLINE convertString #-}; convertString = Lenient . TE.decodeUtf8With lenientDecode . BL.toStrict+instance ConvertString BL.ByteString (Maybe String) where {-# INLINE convertString #-}; convertString = fmap TL.unpack . eitherToMaybe . TLE.decodeUtf8'+instance ConvertString BL.ByteString (Maybe TL.Text) where {-# INLINE convertString #-}; convertString = eitherToMaybe . TLE.decodeUtf8'+instance ConvertString BL.ByteString (Maybe Text) where {-# INLINE convertString #-}; convertString = eitherToMaybe . TE.decodeUtf8' . BL.toStrict+instance ConvertString BL.ByteString BL.ByteString where {-# INLINE convertString #-}; convertString = id+instance ConvertString BL.ByteString ByteString where {-# INLINE convertString #-}; convertString = BL.toStrict+instance ConvertString BL.ByteString ShortByteString where {-# INLINE convertString #-}; convertString = S.toShort . BL.toStrict+instance ConvertString BL.ByteString [Word8] where {-# INLINE convertString #-}; convertString = BL.unpack+instance ConvertString ByteString (Lenient String) where {-# INLINE convertString #-}; convertString = Lenient . T.unpack . TE.decodeUtf8With lenientDecode+instance ConvertString ByteString (Lenient TL.Text) where {-# INLINE convertString #-}; convertString = Lenient . TLE.decodeUtf8With lenientDecode . BL.fromStrict+instance ConvertString ByteString (Lenient Text) where {-# INLINE convertString #-}; convertString = Lenient . TE.decodeUtf8With lenientDecode+instance ConvertString ByteString (Maybe String) where {-# INLINE convertString #-}; convertString = fmap T.unpack . eitherToMaybe . TE.decodeUtf8'+instance ConvertString ByteString (Maybe TL.Text) where {-# INLINE convertString #-}; convertString = eitherToMaybe . TLE.decodeUtf8' . BL.fromStrict+instance ConvertString ByteString (Maybe Text) where {-# INLINE convertString #-}; convertString = eitherToMaybe . TE.decodeUtf8'+instance ConvertString ByteString BL.ByteString where {-# INLINE convertString #-}; convertString = BL.fromStrict+instance ConvertString ByteString ByteString where {-# INLINE convertString #-}; convertString = id+instance ConvertString ByteString ShortByteString where {-# INLINE convertString #-}; convertString = S.toShort+instance ConvertString ByteString [Word8] where {-# INLINE convertString #-}; convertString = B.unpack+instance ConvertString ShortByteString (Lenient String) where {-# INLINE convertString #-}; convertString = Lenient . T.unpack . TE.decodeUtf8With lenientDecode . S.fromShort+instance ConvertString ShortByteString (Lenient TL.Text) where {-# INLINE convertString #-}; convertString = Lenient . TLE.decodeUtf8With lenientDecode . BL.fromStrict . S.fromShort+instance ConvertString ShortByteString (Lenient Text) where {-# INLINE convertString #-}; convertString = Lenient . TE.decodeUtf8With lenientDecode . S.fromShort+instance ConvertString ShortByteString (Maybe String) where {-# INLINE convertString #-}; convertString = fmap T.unpack . eitherToMaybe . TE.decodeUtf8' . S.fromShort+instance ConvertString ShortByteString (Maybe TL.Text) where {-# INLINE convertString #-}; convertString = eitherToMaybe . TLE.decodeUtf8' . BL.fromStrict . S.fromShort+instance ConvertString ShortByteString (Maybe Text) where {-# INLINE convertString #-}; convertString = eitherToMaybe . TE.decodeUtf8' . S.fromShort+instance ConvertString ShortByteString BL.ByteString where {-# INLINE convertString #-}; convertString = BL.fromStrict . S.fromShort+instance ConvertString ShortByteString ByteString where {-# INLINE convertString #-}; convertString = S.fromShort+instance ConvertString ShortByteString ShortByteString where {-# INLINE convertString #-}; convertString = id+instance ConvertString ShortByteString [Word8] where {-# INLINE convertString #-}; convertString = S.unpack+instance ConvertString String BL.ByteString where {-# INLINE convertString #-}; convertString = TLE.encodeUtf8 . TL.pack+instance ConvertString String ByteString where {-# INLINE convertString #-}; convertString = TE.encodeUtf8 . T.pack+instance ConvertString String ShortByteString where {-# INLINE convertString #-}; convertString = S.toShort . TE.encodeUtf8 . T.pack+instance ConvertString String String where {-# INLINE convertString #-}; convertString = id+instance ConvertString String TL.Text where {-# INLINE convertString #-}; convertString = TL.pack+instance ConvertString String Text where {-# INLINE convertString #-}; convertString = T.pack+instance ConvertString String [Word8] where {-# INLINE convertString #-}; convertString = BL.unpack . TLE.encodeUtf8 . TL.pack+instance ConvertString TL.Text BL.ByteString where {-# INLINE convertString #-}; convertString = TLE.encodeUtf8+instance ConvertString TL.Text ByteString where {-# INLINE convertString #-}; convertString = BL.toStrict . TLE.encodeUtf8+instance ConvertString TL.Text ShortByteString where {-# INLINE convertString #-}; convertString = S.toShort . BL.toStrict . TLE.encodeUtf8+instance ConvertString TL.Text String where {-# INLINE convertString #-}; convertString = TL.unpack+instance ConvertString TL.Text TL.Text where {-# INLINE convertString #-}; convertString = id+instance ConvertString TL.Text Text where {-# INLINE convertString #-}; convertString = TL.toStrict+instance ConvertString TL.Text [Word8] where {-# INLINE convertString #-}; convertString = BL.unpack . TLE.encodeUtf8+instance ConvertString Text BL.ByteString where {-# INLINE convertString #-}; convertString = BL.fromStrict . TE.encodeUtf8+instance ConvertString Text ByteString where {-# INLINE convertString #-}; convertString = TE.encodeUtf8+instance ConvertString Text ShortByteString where {-# INLINE convertString #-}; convertString = S.toShort . TE.encodeUtf8+instance ConvertString Text String where {-# INLINE convertString #-}; convertString = T.unpack+instance ConvertString Text TL.Text where {-# INLINE convertString #-}; convertString = TL.fromStrict+instance ConvertString Text Text where {-# INLINE convertString #-}; convertString = id+instance ConvertString Text [Word8] where {-# INLINE convertString #-}; convertString = BL.unpack . BL.fromStrict . TE.encodeUtf8+instance ConvertString [Word8] (Lenient String) where {-# INLINE convertString #-}; convertString = Lenient . TL.unpack . TLE.decodeUtf8With lenientDecode . BL.pack+instance ConvertString [Word8] (Lenient TL.Text) where {-# INLINE convertString #-}; convertString = Lenient . TLE.decodeUtf8With lenientDecode . BL.pack+instance ConvertString [Word8] (Lenient Text) where {-# INLINE convertString #-}; convertString = Lenient . TE.decodeUtf8With lenientDecode . B.pack+instance ConvertString [Word8] (Maybe String) where {-# INLINE convertString #-}; convertString = fmap TL.unpack . eitherToMaybe . TLE.decodeUtf8' . BL.pack+instance ConvertString [Word8] (Maybe TL.Text) where {-# INLINE convertString #-}; convertString = eitherToMaybe . TLE.decodeUtf8' . BL.pack+instance ConvertString [Word8] (Maybe Text) where {-# INLINE convertString #-}; convertString = eitherToMaybe . TE.decodeUtf8' . B.pack+instance ConvertString [Word8] BL.ByteString where {-# INLINE convertString #-}; convertString = BL.pack+instance ConvertString [Word8] ByteString where {-# INLINE convertString #-}; convertString = B.pack+instance ConvertString [Word8] ShortByteString where {-# INLINE convertString #-}; convertString = S.pack+instance ConvertString [Word8] [Word8] where {-# INLINE convertString #-}; convertString = id++instance EncodeString String BL.ByteString+instance EncodeString String ByteString+instance EncodeString String ShortByteString+instance EncodeString String [Word8]+instance EncodeString TL.Text BL.ByteString+instance EncodeString TL.Text ByteString+instance EncodeString TL.Text ShortByteString+instance EncodeString TL.Text [Word8]+instance EncodeString Text BL.ByteString+instance EncodeString Text ByteString+instance EncodeString Text ShortByteString+instance EncodeString Text [Word8]
src/Intro/Trustworthy.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE NoImplicitPrelude #-}@@ -7,7 +6,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Intro.Trustworthy--- Copyright : (c) Daniel Mendler 2016+-- Copyright : (c) Daniel Mendler 2016-2017 -- License : MIT -- -- Maintainer : mail@daniel-mendler.de@@ -19,8 +18,7 @@ ----------------------------------------------------------------------------- module Intro.Trustworthy (- Data.DList.DList- , GHC.Exts.IsList(+ GHC.Exts.IsList( Item , fromList , toList@@ -29,8 +27,10 @@ , HasCallStack , trace , traceIO+ , traceId , traceM , traceShow+ , traceShowId , traceShowM , Data.Hashable.Lifted.Hashable1 , Data.Hashable.Lifted.Hashable2@@ -40,22 +40,12 @@ import Data.Function ((.)) import Data.Text (Text, unpack) import Text.Show (Show)-import qualified Data.DList import qualified Debug.Trace import qualified GHC.Exts import qualified Data.Hashable.Lifted--#if MIN_VERSION_base(4,9,0) import Control.Applicative (Applicative) import Data.Kind (Constraint) import GHC.Stack (HasCallStack)-#define APPLICATIVE Applicative-#else-import Control.Monad (Monad)-import GHC.Exts (Constraint)-type HasCallStack = (() :: GHC.Exts.Constraint)-#define APPLICATIVE Monad-#endif -- | The 'trace' function outputs the trace message given as its first argument, -- before returning the second argument as its result.@@ -70,7 +60,7 @@ -- trace message. trace :: Text -> a -> a trace = Debug.Trace.trace . unpack-{-# WARNING trace "'trace' remains in code" #-}+{-# WARNING trace "'trace' should be used only for debugging" #-} -- | Like 'trace' but returning unit in an arbitrary 'Applicative' context. Allows -- for convenient use in do-notation.@@ -87,9 +77,9 @@ -- > traceM $ "x: " ++ show x -- > y <- ... -- > traceM $ "y: " ++ show y-traceM :: APPLICATIVE m => Text -> m ()+traceM :: Applicative m => Text -> m () traceM = Debug.Trace.traceM . unpack-{-# WARNING traceM "'traceM' remains in code" #-}+{-# WARNING traceM "'traceM' should be used only for debugging" #-} -- | Like 'trace', but uses 'show' on the argument to convert it to a 'String'. --@@ -104,7 +94,7 @@ -- > ... traceShow :: Show a => a -> b -> b traceShow = Debug.Trace.traceShow-{-# WARNING traceShow "'traceShow' remains in code" #-}+{-# WARNING traceShow "'traceShow' should be used only for debugging" #-} -- | Like 'traceM', but uses 'show' on the argument to convert it to a 'String'. --@@ -113,12 +103,22 @@ -- > traceShowM $ x -- > y <- ... -- > traceShowM $ x + y-traceShowM :: (Show a, APPLICATIVE m) => a -> m ()+traceShowM :: (Show a, Applicative m) => a -> m () traceShowM = Debug.Trace.traceShowM-{-# WARNING traceShowM "'traceShowM' remains in code" #-}+{-# WARNING traceShowM "'traceShowM' should be used only for debugging" #-} -- | The 'traceIO' function outputs the trace message from the IO monad. -- This sequences the output with respect to other IO actions. traceIO :: MonadIO m => Text -> m () traceIO = liftIO . Debug.Trace.traceIO . unpack-{-# WARNING traceIO "'traceIO' remains in code" #-}+{-# WARNING traceIO "'traceIO' should be used only for debugging" #-}++-- | Like 'traceShow' but returns the shown value instead of a third value.+traceShowId :: Show a => a -> a+traceShowId = Debug.Trace.traceShowId+{-# WARNING traceShowId "'traceShowId' should be used only for debugging" #-}++-- | Like 'trace' but returns the message instead of a third value.+traceId :: Text -> Text+traceId a = Debug.Trace.trace (unpack a) a+{-# WARNING traceId "'traceId' should be used only for debugging" #-}
test/BaseCompat.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE CPP #-} module BaseCompat ( module X ) where@@ -38,7 +37,7 @@ import Data.IORef as X import Data.Int as X import Data.Ix as X-import Data.List as X hiding (scanl1, scanr1, map)+import Data.List as X hiding (scanl1, scanr1, map, cycle, head, init, last, tail) import Data.Maybe as X import Data.Monoid as X hiding (First(..), Last(..), (<>)) import Data.Ord as X@@ -58,7 +57,7 @@ import Data.Word as X import Numeric as X import Numeric.Natural as X-import Prelude as X hiding ((.), id, map, putChar, putStrLn, putStr, getContents, getLine, print, getChar, appendFile, readFile, writeFile, fail, show, undefined, scanl1, scanr1)+import Prelude as X hiding ((.), id, map, putChar, putStrLn, putStr, getContents, getLine, print, getChar, appendFile, readFile, writeFile, fail, show, undefined, scanl1, scanr1, cycle, head, init, last, tail) import System.CPUTime as X import System.Console.GetOpt as X hiding (Option) import System.Environment as X@@ -77,8 +76,5 @@ import Text.Read as X hiding (readMaybe, get, lift, EOF, (+++)) import Text.Show as X hiding (show) import Unsafe.Coerce as X--#if MIN_VERSION_base(4,9,0) import Control.Monad.Fail as X hiding (fail) import Data.Kind as X-#endif
+ test/OpticsCompat.hs view
@@ -0,0 +1,7 @@+{-# LANGUAGE NoImplicitPrelude #-}+module OpticsCompat (+ module X+) where++import Intro as X+import Optics as X
− test/compat.hs
@@ -1,9 +0,0 @@-{-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE OverloadedStrings #-}-module Main where--import BaseCompat-import LensCompat--main :: IO ()-main = pure ()
+ test/test.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE ExplicitForAll #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Main where++import BaseCompat ()+import Data.ByteString.Short (ShortByteString)+import Intro+import LensCompat ()+import OpticsCompat ()+import Test.QuickCheck+import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as LB+import qualified Data.ByteString.Short as SB+import qualified Data.Text as T+import qualified Data.Text.Lazy as LT++instance Arbitrary ByteString where arbitrary = B.pack <$> arbitrary+instance Arbitrary LB.ByteString where arbitrary = LB.pack <$> arbitrary+instance Arbitrary ShortByteString where arbitrary = SB.pack <$> arbitrary+instance Arbitrary Text where arbitrary = T.pack <$> arbitrary+instance Arbitrary LT.Text where arbitrary = LT.pack <$> arbitrary++main :: IO ()+main = do+ encode (Proxy :: Proxy LText) (Proxy :: Proxy ByteString)+ encode (Proxy :: Proxy LText) (Proxy :: Proxy LByteString)+ encode (Proxy :: Proxy LText) (Proxy :: Proxy ShortByteString)+ encode (Proxy :: Proxy LText) (Proxy :: Proxy [Word8])+ encode (Proxy :: Proxy String) (Proxy :: Proxy ByteString)+ encode (Proxy :: Proxy String) (Proxy :: Proxy LByteString)+ encode (Proxy :: Proxy String) (Proxy :: Proxy ShortByteString)+ encode (Proxy :: Proxy String) (Proxy :: Proxy [Word8])+ encode (Proxy :: Proxy Text) (Proxy :: Proxy ByteString)+ encode (Proxy :: Proxy Text) (Proxy :: Proxy LByteString)+ encode (Proxy :: Proxy Text) (Proxy :: Proxy ShortByteString)+ encode (Proxy :: Proxy Text) (Proxy :: Proxy [Word8])+ iso (Proxy :: Proxy ByteString) (Proxy :: Proxy ByteString)+ iso (Proxy :: Proxy ByteString) (Proxy :: Proxy LByteString)+ iso (Proxy :: Proxy ByteString) (Proxy :: Proxy ShortByteString)+ iso (Proxy :: Proxy ByteString) (Proxy :: Proxy [Word8])+ iso (Proxy :: Proxy ShortByteString) (Proxy :: Proxy ByteString)+ iso (Proxy :: Proxy ShortByteString) (Proxy :: Proxy LByteString)+ iso (Proxy :: Proxy ShortByteString) (Proxy :: Proxy ShortByteString)+ iso (Proxy :: Proxy ShortByteString) (Proxy :: Proxy [Word8])+ iso (Proxy :: Proxy LByteString) (Proxy :: Proxy ByteString)+ iso (Proxy :: Proxy LByteString) (Proxy :: Proxy LByteString)+ iso (Proxy :: Proxy LByteString) (Proxy :: Proxy ShortByteString)+ iso (Proxy :: Proxy LByteString) (Proxy :: Proxy [Word8])+ iso (Proxy :: Proxy LText) (Proxy :: Proxy LText)+ iso (Proxy :: Proxy LText) (Proxy :: Proxy String)+ iso (Proxy :: Proxy LText) (Proxy :: Proxy Text)+ iso (Proxy :: Proxy String) (Proxy :: Proxy LText)+ iso (Proxy :: Proxy String) (Proxy :: Proxy String)+ iso (Proxy :: Proxy String) (Proxy :: Proxy Text)+ iso (Proxy :: Proxy Text) (Proxy :: Proxy LText)+ iso (Proxy :: Proxy Text) (Proxy :: Proxy String)+ iso (Proxy :: Proxy Text) (Proxy :: Proxy Text)+ iso (Proxy :: Proxy [Word8]) (Proxy :: Proxy ByteString)+ iso (Proxy :: Proxy [Word8]) (Proxy :: Proxy LByteString)+ iso (Proxy :: Proxy [Word8]) (Proxy :: Proxy ShortByteString)+ iso (Proxy :: Proxy [Word8]) (Proxy :: Proxy [Word8])++iso :: forall a b proxy. (Eq a, Eq b, Show a, Show b, Arbitrary a, Arbitrary b, ConvertString a b, ConvertString b a) => proxy a -> proxy b -> IO ()+iso _ _ = do+ quickCheck $ \(a :: a) -> convertString (convertString a :: b) == a+ quickCheck $ \(b :: b) -> convertString (convertString b :: a) == b++encode :: forall a b proxy. (Eq a, Show a, Arbitrary a, EncodeString a b) => proxy a -> proxy b -> IO ()+encode _ _ = do+ quickCheck $ \(a :: a) -> decodeString (encodeString a :: b) == Just a+ quickCheck $ \(a :: a) -> decodeStringLenient (encodeString a :: b) == a