packages feed

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 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