intro 0.1.0.10 → 0.2.0.0
raw patch · 7 files changed
+223/−32 lines, 7 filesdep +QuickCheckdep +quickcheck-instancesdep −string-conversionsPVP ok
version bump matches the API change (PVP)
Dependencies added: QuickCheck, quickcheck-instances
Dependencies removed: string-conversions
API changes (from Hackage documentation)
- Intro: class ConvertibleStrings a b
+ Intro: Lenient :: a -> Lenient a
+ Intro: [getLenient] :: Lenient a -> a
+ Intro: class ConvertString a b
+ Intro: class (ConvertString a b, ConvertString b (Maybe a), ConvertString b (Lenient a)) => EncodeString a b where encodeString = convertString decodeStringLenient = getLenient . convertString decodeString = convertString
+ Intro: decodeString :: EncodeString a b => b -> Maybe a
+ Intro: decodeStringLenient :: EncodeString a b => b -> a
+ Intro: encodeString :: EncodeString a b => a -> b
+ Intro: newtype Lenient a
- Intro: convertString :: ConvertibleStrings a b => a -> b
+ Intro: convertString :: ConvertString a b => a -> b
- Intro: readMaybe :: (Read b, ConvertibleStrings a String) => a -> Maybe b
+ Intro: readMaybe :: (Read b, ConvertString a String) => a -> Maybe b
- Intro: show :: (Show a, IsString s) => a -> s
+ Intro: show :: (Show a, ConvertString String s) => a -> s
Files
- LICENSE +1/−1
- intro.cabal +7/−6
- src/Intro.hs +16/−15
- src/Intro/ConvertString.hs +148/−0
- src/Intro/Trustworthy.hs +1/−1
- test/compat.hs +0/−9
- test/test.hs +50/−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
intro.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack name: intro-version: 0.1.0.10+version: 0.2.0.0 synopsis: "Fixed Prelude" - Mostly total and safe, provides Text and Monad transformers description: Intro is a modern Prelude which provides safe alternatives for most of the partial functions and follows other@@ -22,7 +22,7 @@ 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@@ -52,7 +52,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@@ -64,13 +63,14 @@ exposed-modules: Intro other-modules:+ Intro.ConvertString Intro.Trustworthy Paths_intro default-language: Haskell2010 -test-suite compat+test-suite test type: exitcode-stdio-1.0- main-is: compat.hs+ main-is: test.hs hs-source-dirs: test ghc-options: -Wall@@ -86,7 +86,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@@ -94,6 +93,8 @@ , writer-cps-mtl >= 0.1.1.2 && < 0.2 , intro , lens+ , QuickCheck+ , quickcheck-instances if impl(ghc < 8.0) build-depends: semigroups >= 0.9 && < 1
src/Intro.hs view
@@ -9,7 +9,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Intro--- Copyright : (c) Daniel Mendler 2016+-- Copyright : (c) Daniel Mendler 2016-2017 -- License : MIT -- -- Maintainer : mail@daniel-mendler.de@@ -34,11 +34,11 @@ -- * 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 --@@ -70,7 +70,7 @@ -- * '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: --@@ -187,7 +187,6 @@ , Data.List.zip3 , Data.List.zipWith , Data.List.zipWith3- -- , Data.List.cycle -- partial , Safe.headDef , Safe.headMay -- prefer pattern match , Safe.initDef@@ -245,7 +244,9 @@ -- ** Conversion , Data.String.IsString(fromString)- , Data.String.Conversions.ConvertibleStrings(convertString)+ , Intro.ConvertString.ConvertString(convertString)+ , Intro.ConvertString.EncodeString(encodeString, decodeString, decodeStringLenient)+ , Lenient(..) -- * Container types @@ -668,11 +669,10 @@ 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.ConvertString+import Intro.Trustworthy import System.IO (FilePath)-import Text.Read (Read) import Text.Show (Show) import qualified Control.Applicative import qualified Control.Category@@ -729,7 +729,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@@ -769,9 +768,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 +785,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 #-} @@ -870,10 +869,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.
+ src/Intro/ConvertString.hs view
@@ -0,0 +1,148 @@+-----------------------------------------------------------------------------+-- |+-- Module : Intro.ConvertString+-- Copyright : (c) Daniel Mendler 2017+-- License : MIT+--+-- Maintainer : mail@daniel-mendler.de+-- Stability : experimental+-- Portability : portable+--+-- String conversion and decoding+--+-----------------------------------------------------------------------------++{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE Safe #-}+{-# LANGUAGE DefaultSignatures #-}++module Intro.ConvertString (+ ConvertString(..)+ , EncodeString(..)+ , Lenient(..)+) where++import Data.ByteString (ByteString)+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 Text.Show (Show)+import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as BL+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, Show, Functor, Foldable, Traversable)++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 [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 [Word8] where {-# INLINE convertString #-}; convertString = B.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 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 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 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] [Word8] where {-# INLINE convertString #-}; convertString = id++instance EncodeString String BL.ByteString+instance EncodeString String ByteString+instance EncodeString String [Word8]+instance EncodeString TL.Text BL.ByteString+instance EncodeString TL.Text ByteString+instance EncodeString TL.Text [Word8]+instance EncodeString Text BL.ByteString+instance EncodeString Text ByteString+instance EncodeString Text [Word8]
src/Intro/Trustworthy.hs view
@@ -7,7 +7,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Intro.Trustworthy--- Copyright : (c) Daniel Mendler 2016+-- Copyright : (c) Daniel Mendler 2016-2017 -- License : MIT -- -- Maintainer : mail@daniel-mendler.de
− 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,50 @@+{-# LANGUAGE ExplicitForAll #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Main where++import Intro+import BaseCompat ()+import LensCompat ()+import Test.QuickCheck+import Test.QuickCheck.Instances ()++main :: IO ()+main = do+ encode (Proxy :: Proxy LText) (Proxy :: Proxy ByteString)+ encode (Proxy :: Proxy LText) (Proxy :: Proxy LByteString)+ 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 [Word8])+ encode (Proxy :: Proxy Text) (Proxy :: Proxy ByteString)+ encode (Proxy :: Proxy Text) (Proxy :: Proxy LByteString)+ 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 [Word8])+ iso (Proxy :: Proxy LByteString) (Proxy :: Proxy ByteString)+ iso (Proxy :: Proxy LByteString) (Proxy :: Proxy LByteString)+ 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 [Word8])++iso :: forall a b proxy. (Eq a, Show a, Arbitrary a, ConvertString a b, ConvertString b a) => proxy a -> proxy b -> IO ()+iso _ _ = quickCheck $ \(a :: a) -> convertString (convertString a :: b) == a++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