incipit-base (empty) → 0.1.0.0
raw patch · 15 files changed
+1450/−0 lines, 15 filesdep +basedep +bytestringdep +containerssetup-changed
Dependencies added: base, bytestring, containers, data-default, text
Files
- LICENSE +34/−0
- Setup.hs +2/−0
- changelog.md +0/−0
- incipit-base.cabal +128/−0
- lib/Incipit/Base.hs +201/−0
- lib/Incipit/Debug.hs +111/−0
- lib/Incipit/Either.hs +30/−0
- lib/Incipit/Libraries.hs +19/−0
- lib/Incipit/List.hs +33/−0
- lib/Incipit/Misc.hs +43/−0
- lib/Incipit/Prelude.hs +25/−0
- lib/Incipit/String.hs +57/−0
- lib/Incipit/String/Conversion.hs +553/−0
- lib/Incipit/String/Reexport.hs +209/−0
- readme.md +5/−0
+ LICENSE view
@@ -0,0 +1,34 @@+Copyright (c) 2022 Torsten Schmits++Redistribution and use in source and binary forms, with or without modification, are permitted provided that the+following conditions are met:++ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following+ disclaimer.+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided with the distribution.++Subject to the terms and conditions of this license, each copyright holder and contributor hereby grants to those+receiving rights under this license a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except+for failure to satisfy the conditions of this license) patent license to make, have made, use, offer to sell, sell,+import, and otherwise transfer this software, where such license applies only to those patent claims, already acquired+or hereafter acquired, licensable by such copyright holder or contributor that are necessarily infringed by:++ (a) their Contribution(s) (the licensed copyrights of copyright holders and non-copyrightable additions of+ contributors, in source or binary form) alone; or+ (b) combination of their Contribution(s) with the work of authorship to which such Contribution(s) was added by such+ copyright holder or contributor, if, at the time the Contribution is added, such addition causes such combination to+ be necessarily infringed. The patent license shall not apply to any other combinations which include the Contribution.++Except as expressly stated above, no rights or licenses from any copyright holder or contributor is granted under this+license, whether expressly, by implication, estoppel or otherwise.++DISCLAIMER++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ changelog.md view
+ incipit-base.cabal view
@@ -0,0 +1,128 @@+cabal-version: 2.2++-- This file has been generated from package.yaml by hpack version 0.34.6.+--+-- see: https://github.com/sol/hpack++name: incipit-base+version: 0.1.0.0+synopsis: A Prelude for Polysemy+description: See <https://hackage.haskell.org/package/incipit-base/docs/Incipit-Prelude.html>+category: Prelude+homepage: https://github.com/tek/incipit#readme+bug-reports: https://github.com/tek/incipit/issues+author: Torsten Schmits+maintainer: haskell@tryp.io+copyright: 2022 Torsten Schmits+license: BSD-2-Clause-Patent+license-file: LICENSE+build-type: Simple+extra-source-files:+ readme.md+ changelog.md++source-repository head+ type: git+ location: https://github.com/tek/incipit++library+ exposed-modules:+ Incipit.Base+ Incipit.Debug+ Incipit.Either+ Incipit.Libraries+ Incipit.List+ Incipit.Misc+ Incipit.Prelude+ Incipit.String+ Incipit.String.Conversion+ Incipit.String.Reexport+ reexported-modules:+ Data.ByteString+ , Data.ByteString.Builder+ , Data.ByteString.Lazy+ , Data.ByteString.Short+ , Data.IntMap.Lazy+ , Data.IntMap.Strict+ , Data.IntSet+ , Data.Map.Lazy+ , Data.Map.Strict+ , Data.Sequence+ , Data.Set+ , Data.Text+ , Data.Text.IO+ , Data.Text.Lazy+ , Data.Text.Lazy.IO+ , Data.Text.Read+ , Data.Tree+ hs-source-dirs:+ lib+ default-extensions:+ AllowAmbiguousTypes+ ApplicativeDo+ BangPatterns+ BinaryLiterals+ BlockArguments+ ConstraintKinds+ DataKinds+ DefaultSignatures+ DeriveAnyClass+ DeriveDataTypeable+ DeriveFoldable+ DeriveFunctor+ DeriveGeneric+ DeriveTraversable+ DerivingStrategies+ DerivingVia+ DisambiguateRecordFields+ DoAndIfThenElse+ DuplicateRecordFields+ EmptyDataDecls+ ExistentialQuantification+ FlexibleContexts+ FlexibleInstances+ FunctionalDependencies+ GADTs+ GeneralizedNewtypeDeriving+ InstanceSigs+ KindSignatures+ LambdaCase+ LiberalTypeSynonyms+ MultiParamTypeClasses+ MultiWayIf+ NamedFieldPuns+ NoImplicitPrelude+ OverloadedStrings+ OverloadedLists+ PackageImports+ PartialTypeSignatures+ PatternGuards+ PatternSynonyms+ PolyKinds+ QuantifiedConstraints+ QuasiQuotes+ RankNTypes+ RecordWildCards+ RecursiveDo+ ScopedTypeVariables+ StandaloneDeriving+ TemplateHaskell+ TupleSections+ TypeApplications+ TypeFamilies+ TypeFamilyDependencies+ TypeOperators+ TypeSynonymInstances+ UndecidableInstances+ UnicodeSyntax+ ViewPatterns+ ghc-options: -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wmissing-deriving-strategies -Widentities+ build-depends:+ base ==4.*+ , bytestring+ , containers+ , data-default >=0.2+ , text+ if impl(ghc >= 8.10)+ ghc-options: -Wunused-packages+ default-language: Haskell2010
+ lib/Incipit/Base.hs view
@@ -0,0 +1,201 @@+{-# options_haddock ignore-exports #-}++-- |Reexports from @base@.+module Incipit.Base (+ module Control.Applicative,+ module Control.Arrow,+ module Control.Category,+ module Control.Monad,+ module Control.Monad.Fail,+ module Data.Bifunctor,+ module Data.Bits,+ module Data.Bool,+ module Data.Char,+ module Data.Coerce,+ module Data.Either,+ module Data.Eq,+ module Data.Foldable,+ module Data.Function,+ module Data.Functor,+ module Data.Functor.Compose,+ module Data.Functor.Contravariant,+ module Data.Functor.Identity,+ module Data.Int,+ module Data.Kind,+ module Data.List,+ module Data.List.NonEmpty,+ module Data.Maybe,+ module Data.Monoid,+ module Data.Ord,+ module Data.Proxy,+ module Data.Semigroup,+ module Data.Traversable,+ module Data.Tuple,+ module Data.Typeable,+ module Data.Void,+ module Data.Word,+ module GHC.Base,+ module GHC.Enum,+ module GHC.Err,+ module GHC.Float,+ module GHC.Generics,+ module GHC.Num,+ module GHC.OverloadedLabels,+ module GHC.Real,+ module GHC.Show,+ module GHC.Stack,+ module GHC.TypeLits,+ module Numeric.Natural,+ module System.IO,+) where++import Control.Applicative (+ Alternative (..),+ Applicative (..),+ Const (..),+ ZipList (..),+ liftA2,+ liftA3,+ optional,+ (<**>),+ )+import Control.Arrow ((&&&))+import Control.Category ((<<<), (>>>))+import Control.Monad (+ Monad ((>>), (>>=)),+ MonadPlus (..),+ filterM,+ forever,+ guard,+ join,+ mfilter,+ replicateM,+ replicateM_,+ unless,+ when,+ zipWithM,+ zipWithM_,+ (<$!>),+ (<=<),+ (=<<),+ (>=>),+ )+import Control.Monad.Fail (MonadFail (..))+import Data.Bifunctor (Bifunctor (..))+import Data.Bits (toIntegralSized, xor)+import Data.Bool (Bool (..), bool, not, otherwise, (&&), (||))+import Data.Char (Char, chr)+import Data.Coerce (Coercible, coerce)+import Data.Either+import Data.Eq (Eq (..))+import Data.Foldable (+ Foldable (..),+ all,+ and,+ any,+ asum,+ concat,+ concatMap,+ find,+ foldlM,+ forM_,+ for_,+ mapM_,+ or,+ sequenceA_,+ sequence_,+ traverse_,+ )+import Data.Function (const, fix, flip, id, on, ($), (&), (.))+import Data.Functor (Functor (..), void, ($>), (<$>), (<&>))+import Data.Functor.Compose (Compose (..))+import Data.Functor.Contravariant (Contravariant (..), (>$<))+import Data.Functor.Identity (Identity (..))+import Data.Int (Int, Int16, Int32, Int64, Int8)+import Data.Kind (Constraint, Type)+import Data.List (+ break,+ drop,+ dropWhile,+ filter,+ genericDrop,+ genericLength,+ genericReplicate,+ genericSplitAt,+ genericTake,+ group,+ inits,+ intercalate,+ intersperse,+ isPrefixOf,+ iterate,+ map,+ permutations,+ repeat,+ replicate,+ reverse,+ scanl,+ scanl',+ scanl1,+ scanr,+ scanr1,+ sort,+ sortBy,+ sortOn,+ span,+ splitAt,+ subsequences,+ tails,+ take,+ takeWhile,+ transpose,+ uncons,+ unfoldr,+ unzip,+ unzip3,+ zip,+ zip3,+ zipWith,+ (++),+ )+import Data.List.NonEmpty (NonEmpty (..), nonEmpty)+import Data.Maybe hiding (fromJust)+import Data.Monoid (Monoid (..))+import Data.Ord (Down (..), Ord (..), Ordering (..), comparing)+import Data.Proxy (Proxy (..))+import Data.Semigroup (Semigroup (..))+import Data.Traversable (Traversable (..), for, forM, mapAccumL, mapAccumR)+import Data.Tuple (curry, fst, snd, swap, uncurry)+import Data.Typeable (Typeable)+import Data.Void (Void)+import Data.Word (Word, Word16, Word32, Word64, Word8, byteSwap16, byteSwap32, byteSwap64)+import GHC.Base (maxInt, minInt, ord, seq, ($!))+import GHC.Enum (Bounded (..), Enum (..))+import GHC.Err (error, undefined)+import GHC.Float (Double (..), Float (..))+import GHC.Generics (Generic)+import GHC.Num (Integer, Num (..), subtract)+import GHC.OverloadedLabels (IsLabel (..))+import GHC.Real (+ Fractional (..),+ Integral (..),+ Ratio,+ Rational,+ Real (..),+ RealFrac (..),+ denominator,+ even,+ fromIntegral,+ gcd,+ lcm,+ numerator,+ odd,+ realToFrac,+ (^),+ (^^),+ )+import GHC.Show (Show)+import GHC.Stack (HasCallStack)+import GHC.TypeLits hiding (ErrorMessage (Text))+import Numeric.Natural (Natural)+import System.IO (FilePath, IO, print, putStr, putStrLn)
+ lib/Incipit/Debug.hs view
@@ -0,0 +1,111 @@+{-# options_haddock prune #-}++-- |Utility functions for trace-printing values prefixed with the current source location.+module Incipit.Debug where++import qualified Data.Text as Text+import GHC.Stack (CallStack, SrcLoc (..), callStack, getCallStack)+import System.IO.Unsafe (unsafePerformIO)++import Incipit.Base (+ Applicative (pure),+ Functor ((<$)),+ HasCallStack,+ IO,+ Monad,+ Semigroup ((<>)),+ Show,+ error,+ fromMaybe,+ putStrLn,+ )+import Incipit.List (last)+import Incipit.String.Conversion (ToString (toString), ToText (toText), show)+import Data.Text (Text)++srcLoc :: CallStack -> SrcLoc+srcLoc = \case+ (getCallStack -> (_, loc) : _) -> loc+ _ -> error "Debug.srcLoc: empty CallStack"++debugPrint ::+ SrcLoc ->+ Text ->+ IO ()+debugPrint SrcLoc {srcLocModule = (toText -> slm), srcLocStartLine} msg =+ putStrLn (toString moduleName <> ":" <> show srcLocStartLine <> " " <> toString msg)+ where+ moduleName =+ fromMaybe slm (last (Text.splitOn "." slm))++debugPrintWithLoc ::+ Monad m =>+ SrcLoc ->+ Text ->+ m ()+debugPrintWithLoc loc msg = do+ () <- pure (unsafePerformIO (debugPrint loc msg))+ pure ()++-- |Print a 'Text' in an arbitrary 'Monad'.+dbg ::+ HasCallStack =>+ Monad m =>+ Text ->+ m ()+dbg =+ debugPrintWithLoc (srcLoc callStack)+{-# noinline dbg #-}++-- |Print a value with a 'Show' instance in an arbitrary 'Monad'.+dbgs ::+ HasCallStack =>+ Monad m =>+ Show a =>+ a ->+ m ()+dbgs a =+ debugPrintWithLoc (srcLoc callStack) (show a)+{-# noinline dbgs_ #-}++-- |Print a value with a 'Show' instance in an arbitrary 'Monad', returning the value.+dbgs_ ::+ HasCallStack =>+ Monad m =>+ Show a =>+ a ->+ m a+dbgs_ a =+ a <$ debugPrintWithLoc (srcLoc callStack) (show a)+{-# noinline dbgs #-}++-- |Like 'Debug.Trace.trace', but with 'Text' and with source location prefix.+tr ::+ HasCallStack =>+ Text ->+ a ->+ a+tr msg a =+ unsafePerformIO (a <$ debugPrint (srcLoc callStack) msg)+{-# noinline tr #-}++-- |Like 'Debug.Trace.traceShowId', but with 'Text' and with source location prefix.+trs ::+ Show a =>+ HasCallStack =>+ a ->+ a+trs a =+ unsafePerformIO (a <$ debugPrint (srcLoc callStack) (show a))+{-# noinline trs #-}++-- |Like 'Debug.Trace.traceShow', but with 'Text' and with source location prefix.+trs' ::+ Show b =>+ HasCallStack =>+ b ->+ a ->+ a+trs' b a =+ unsafePerformIO (a <$ debugPrint (srcLoc callStack) (show b))+{-# noinline trs' #-}
+ lib/Incipit/Either.hs view
@@ -0,0 +1,30 @@+-- |Some utilities for working with 'Either'.+module Incipit.Either where++import Incipit.Base++-- |Turn 'Left' into 'Just' and 'Right' into 'Nothing'.+leftToMaybe :: Either l r -> Maybe l+leftToMaybe = either Just (const Nothing)+{-# inline leftToMaybe #-}++-- |Turn 'Right' into 'Just' and 'Left' into 'Nothing'.+rightToMaybe :: Either l r -> Maybe r+rightToMaybe = either (const Nothing) Just+{-# inline rightToMaybe #-}++-- |Turn 'Just' into 'Right' and 'Nothing' into 'Left' with the supplied value.+maybeToRight :: l -> Maybe r -> Either l r+maybeToRight l = maybe (Left l) Right+{-# inline maybeToRight #-}++-- |Turn 'Just' into 'Left' and 'Nothing' into 'Right' with the supplied value.+maybeToLeft :: r -> Maybe l -> Either l r+maybeToLeft r = maybe (Right r) Left+{-# inline maybeToLeft #-}++-- |Extract the value from either side of an 'Either'.+unify :: Either a a -> a+unify =+ either id id+{-# inline unify #-}
+ lib/Incipit/Libraries.hs view
@@ -0,0 +1,19 @@+{-# options_haddock prune, ignore-exports #-}++-- |Reexports of types from [containers](https://hackage.haskell.org/package/containers) and+-- [data-default](https://hackage.haskell.org/package/data-default).+module Incipit.Libraries (+ module Data.Default,+ module Data.IntMap.Strict,+ module Data.IntSet,+ module Data.Map.Strict,+ module Data.Sequence,+ module Data.Set,+) where++import Data.Default (Default (..))+import Data.IntMap.Strict (IntMap)+import Data.IntSet (IntSet)+import Data.Map.Strict (Map)+import Data.Sequence (Seq)+import Data.Set (Set)
+ lib/Incipit/List.hs view
@@ -0,0 +1,33 @@+-- |Variants of the uncons and unsnoc combinators for lists that return 'Maybe'.+module Incipit.List where++import qualified Data.List as List+import Prelude (Maybe (..))++-- |Return 'Just' the head of a list.+head :: [a] -> Maybe a+head = \case+ [] -> Nothing+ a : _ -> Just a+{-# inline head #-}++-- |Return 'Just' the last element of a list.+last :: [a] -> Maybe a+last = \case+ [] -> Nothing+ as -> Just (List.last as)+{-# inline last #-}++-- |Return 'Just' the non-last elements of a list.+init :: [a] -> Maybe [a]+init = \case+ [] -> Nothing+ as -> Just (List.init as)+{-# inline init #-}++-- |Return 'Just' the non-head elements of a list.+tail :: [a] -> Maybe [a]+tail = \case+ [] -> Nothing+ as -> Just (List.tail as)+{-# inline tail #-}
+ lib/Incipit/Misc.hs view
@@ -0,0 +1,43 @@+-- |Misc combinators.+module Incipit.Misc where++import Incipit.Base++-- |Convenience alias for @pure ()@.+unit ::+ Applicative f =>+ f ()+unit =+ pure ()+{-# inline unit #-}++-- |Variant of 'when' that takes a monadic action for the condition.+whenM ::+ Monad m =>+ m Bool ->+ m () ->+ m ()+whenM condM action =+ condM >>= \ cond -> when cond action+{-# inline whenM #-}++-- |Variant of 'unless' that takes a monadic action for the condition.+unlessM ::+ Monad m =>+ m Bool ->+ m () ->+ m ()+unlessM condM action =+ condM >>= \ cond -> unless cond action+{-# inline unlessM #-}++-- |Variant of @if@/@then@/@else@ that takes a monadic action for the condition and branches.+ifM ::+ Monad m =>+ m Bool ->+ m a ->+ m a ->+ m a+ifM condM onTrue onFalse =+ condM >>= \ cond -> if cond then onTrue else onFalse+{-# inline ifM #-}
+ lib/Incipit/Prelude.hs view
@@ -0,0 +1,25 @@+{-# options_haddock prune #-}++-- |This module is intended to be used by the packages [incipit-core](https://hackage.haskell.org/package/incipit-core)+-- and [incipit](https://hackage.haskell.org/package/incipit), which are Preludes for packages using+-- [Polysemy](https://hackage.haskell.org/package/polysemy).+--+-- Aside from a few additional names from @base@, this module also exports the string system from+-- [relude](https://hackage.haskell.org/package/relude), some tracing functions, and a small set of other combinators.+module Incipit.Prelude (+ module Incipit.Base,+ module Incipit.Debug,+ module Incipit.Either,+ module Incipit.Libraries,+ module Incipit.List,+ module Incipit.Misc,+ module Incipit.String,+) where++import Incipit.Base+import Incipit.Debug+import Incipit.Either+import Incipit.Libraries+import Incipit.List+import Incipit.Misc+import Incipit.String
+ lib/Incipit/String.hs view
@@ -0,0 +1,57 @@+{- |+Copyright: (c) 2016 Stephen Diehl+ (c) 2016-2018 Serokell+ (c) 2018-2021 Kowainik+SPDX-License-Identifier: MIT+Maintainer: Kowainik <xrom.xkov@gmail.com>+Stability: Stable+Portability: Portable++Type classes for conversion between different string representations.++The table below represents the @relude@ concept of conversion between the following types:++* 'Text'+* 'String'+* 'ByteString'+* 'LText'+* 'LByteString'+* 'ShortByteString'++++-----------------------+---------------------+--------------+--------------+--------------------+------------------------+--------------------------++| From \\ To | 'Text' | 'String' | 'ByteString' | 'LText' | 'LByteString' | 'ShortByteString' |++=======================+=====================+==============+==============+====================+========================+==========================++| __'Text'__ | ~ | 'toString' | 'encodeUtf8' | 'toLazy'/'toLText' | 'encodeUtf8' | 'encodeUtf8' |++-----------------------+---------------------+--------------+--------------+--------------------+------------------------+--------------------------++| __'String'__ | 'toText' | ~ | 'encodeUtf8' | 'toLText' | 'encodeUtf8' | 'encodeUtf8' |++-----------------------+---------------------+--------------+--------------+--------------------+------------------------+--------------------------++| __'ByteString'__ | 'decodeUtf8' | 'decodeUtf8' | ~ | 'decodeUtf8' | 'toLazy' | 'toShort' |++-----------------------+---------------------+--------------+--------------+--------------------+------------------------+--------------------------++| __'LText'__ | 'toStrict'/'toText' | 'toString' | 'encodeUtf8' | ~ | 'encodeUtf8' | 'encodeUtf8' |++-----------------------+---------------------+--------------+--------------+--------------------+------------------------+--------------------------++| __'LByteString'__ | 'decodeUtf8' | 'decodeUtf8' | 'toStrict' | 'decodeUtf8' | ~ | @'toShort' . 'toStrict'@ |++-----------------------+---------------------+--------------+--------------+--------------------+------------------------+--------------------------++| __'ShortByteString'__ | 'decodeUtf8' | 'decodeUtf8' | 'fromShort' | 'decodeUtf8' |@'toLazy' . 'fromShort'@| ~ |++-----------------------+---------------------+--------------+--------------+--------------------+------------------------+--------------------------+++-}++module Incipit.String+ ( module Incipit.String.Reexport+ -- $reexport+ , module Incipit.String.Conversion+ -- $conversion+ ) where++import Incipit.String.Conversion+import Incipit.String.Reexport++{- $reexport+Reexport data types and functions to work with 'Text', 'ByteString',+'ShortByteString'.+-}+{- $conversion+Conversion functions between 'Text', 'String', 'ByteString'.+Also some read|show helper functions.+-}
+ lib/Incipit/String/Conversion.hs view
@@ -0,0 +1,553 @@+{-# options_haddock prune #-}++{- |+Copyright: (c) 2016 Stephen Diehl+ (c) 2016-2018 Serokell+ (c) 2018-2021 Kowainik+SPDX-License-Identifier: MIT+Maintainer: Kowainik <xrom.xkov@gmail.com>+Stability: Stable+Portability: Portable++This module implements type class which allow to have conversion to and from+'Incipit.String.Reexport.Text', 'String' and 'ByteString' types+(including both strict and lazy versions). Usually you need to export+'Incipit.String.Reexport.Text' modules qualified and use 'T.pack' \/ 'T.unpack'+functions to convert to\/from 'Incipit.String.Reexport.Text'. Now you can just+use 'toText' \/ 'toString' functions.+-}++module Incipit.String.Conversion+ ( -- * Convenient type aliases+ LText+ , LByteString++ -- * Conversion type classes+ , ConvertUtf8 (..)+ , ToText (..)+ , ToLText (..)+ , ToString (..)+ , LazyStrict (..)+ , fromLazy+ , fromStrict++ -- * Show and read functions+ , readEither+ , show+ ) where++import qualified Data.ByteString.Lazy as LB+import qualified Data.Text as T+import qualified Data.Text.Encoding as T+import qualified Data.Text.Encoding.Error as T+import qualified Data.Text.Lazy as LT+import qualified Data.Text.Lazy.Encoding as LT+import qualified GHC.Show as Show (Show (show))+import qualified GHC.TypeLits as Error+import qualified Text.Read (readEither)++import Incipit.Base+import Incipit.String.Reexport (+ ByteString,+ IsString,+ Read,+ ShortByteString,+ String,+ Text,+ fromShort,+ fromString,+ toShort,+ )+++-- $setup+-- >>> import Relude++-- | Type synonym for 'Data.Text.Lazy.Text'.+type LText = LT.Text++-- | Type synonym for 'Data.ByteString.Lazy.ByteString'.+type LByteString = LB.ByteString+++-- | Type class for conversion to utf8 representation of text.+class ConvertUtf8 a b where+ -- | Encode as utf8 string (usually 'B.ByteString').+ --+ -- >>> encodeUtf8 @Text @ByteString "патак"+ -- "\208\191\208\176\209\130\208\176\208\186"+ encodeUtf8 :: a -> b++ -- | Decode from utf8 string.+ --+ -- >>> decodeUtf8 @Text @ByteString "\208\191\208\176\209\130\208\176\208\186"+ -- "\1087\1072\1090\1072\1082"+ -- >>> putTextLn $ decodeUtf8 @Text @ByteString "\208\191\208\176\209\130\208\176\208\186"+ -- патак+ decodeUtf8 :: b -> a++ {- | Decode as utf8 string but returning execption if byte sequence is malformed.++#if MIN_VERSION_text(1,2,3)+ >>> decodeUtf8 @Text @ByteString "\208\208\176\209\130\208\176\208\186"+ "\65533\1072\1090\1072\1082"+#else+ >>> decodeUtf8 @Text @ByteString "\208\208\176\209\130\208\176\208\186"+ "\65533\65533\1090\1072\1082"+#endif+ >>> decodeUtf8Strict @Text @ByteString "\208\208\176\209\130\208\176\208\186"+ Left Cannot decode byte '\xd0': Data.Text.Internal.Encoding.decodeUtf8: Invalid UTF-8 stream+ -}+ decodeUtf8Strict :: b -> Either T.UnicodeException a++instance ConvertUtf8 String ByteString where+ encodeUtf8 :: String -> ByteString+ encodeUtf8 = T.encodeUtf8 . T.pack+ {-# INLINE encodeUtf8 #-}++ decodeUtf8 :: ByteString -> String+ decodeUtf8 = T.unpack . T.decodeUtf8+ {-# INLINE decodeUtf8 #-}++ decodeUtf8Strict :: ByteString -> Either T.UnicodeException String+ decodeUtf8Strict = (T.unpack <$>) . decodeUtf8Strict+ {-# INLINE decodeUtf8Strict #-}++instance ConvertUtf8 Text ByteString where+ encodeUtf8 :: Text -> ByteString+ encodeUtf8 = T.encodeUtf8+ {-# INLINE encodeUtf8 #-}++ decodeUtf8 :: ByteString -> Text+ decodeUtf8 = T.decodeUtf8With T.lenientDecode+ {-# INLINE decodeUtf8 #-}++ decodeUtf8Strict :: ByteString -> Either T.UnicodeException Text+ decodeUtf8Strict = T.decodeUtf8'+ {-# INLINE decodeUtf8Strict #-}++instance ConvertUtf8 LText ByteString where+ encodeUtf8 :: LText -> ByteString+ encodeUtf8 = LB.toStrict . encodeUtf8+ {-# INLINE encodeUtf8 #-}++ decodeUtf8 :: ByteString -> LText+ decodeUtf8 = LT.decodeUtf8With T.lenientDecode . LB.fromStrict+ {-# INLINE decodeUtf8 #-}++ decodeUtf8Strict :: ByteString -> Either T.UnicodeException LText+ decodeUtf8Strict = decodeUtf8Strict . LB.fromStrict+ {-# INLINE decodeUtf8Strict #-}++{- | Converting 'String' to 'LB.ByteString' might be a slow operation.+Consider using lazy bytestring at first place.+-}+instance ConvertUtf8 String LByteString where+ encodeUtf8 :: String -> LByteString+ encodeUtf8 = LT.encodeUtf8 . LT.pack+ {-# INLINE encodeUtf8 #-}++ decodeUtf8 :: LByteString -> String+ decodeUtf8 = LT.unpack . LT.decodeUtf8+ {-# INLINE decodeUtf8 #-}++ decodeUtf8Strict :: LByteString -> Either T.UnicodeException String+ decodeUtf8Strict = (T.unpack <$>) . decodeUtf8Strict+ {-# INLINE decodeUtf8Strict #-}++instance ConvertUtf8 Text LByteString where+ encodeUtf8 :: Text -> LByteString+ encodeUtf8 = LB.fromStrict . T.encodeUtf8+ {-# INLINE encodeUtf8 #-}++ decodeUtf8 :: LByteString -> Text+ decodeUtf8 = T.decodeUtf8With T.lenientDecode . LB.toStrict+ {-# INLINE decodeUtf8 #-}++ decodeUtf8Strict :: LByteString -> Either T.UnicodeException Text+ decodeUtf8Strict = T.decodeUtf8' . LB.toStrict+ {-# INLINE decodeUtf8Strict #-}++instance ConvertUtf8 LText LByteString where+ encodeUtf8 :: LText -> LByteString+ encodeUtf8 = LT.encodeUtf8+ {-# INLINE encodeUtf8 #-}++ decodeUtf8 :: LByteString -> LText+ decodeUtf8 = LT.decodeUtf8With T.lenientDecode+ {-# INLINE decodeUtf8 #-}++ decodeUtf8Strict :: LByteString -> Either T.UnicodeException LText+ decodeUtf8Strict = LT.decodeUtf8'+ {-# INLINE decodeUtf8Strict #-}++-- | @since 0.6.0.0+instance ConvertUtf8 String ShortByteString where+ encodeUtf8 :: String -> ShortByteString+ encodeUtf8 = toShort . encodeUtf8+ {-# INLINE encodeUtf8 #-}++ decodeUtf8 :: ShortByteString -> String+ decodeUtf8 = decodeUtf8 . fromShort+ {-# INLINE decodeUtf8 #-}++ decodeUtf8Strict :: ShortByteString -> Either T.UnicodeException String+ decodeUtf8Strict = decodeUtf8Strict . fromShort+ {-# INLINE decodeUtf8Strict #-}++-- | @since 0.6.0.0+instance ConvertUtf8 Text ShortByteString where+ encodeUtf8 :: Text -> ShortByteString+ encodeUtf8 = toShort . encodeUtf8+ {-# INLINE encodeUtf8 #-}++ decodeUtf8 :: ShortByteString -> Text+ decodeUtf8 = decodeUtf8 . fromShort+ {-# INLINE decodeUtf8 #-}++ decodeUtf8Strict :: ShortByteString -> Either T.UnicodeException Text+ decodeUtf8Strict = decodeUtf8Strict . fromShort+ {-# INLINE decodeUtf8Strict #-}++-- | @since 0.6.0.0+instance ConvertUtf8 LText ShortByteString where+ encodeUtf8 :: LText -> ShortByteString+ encodeUtf8 = toShort . encodeUtf8+ {-# INLINE encodeUtf8 #-}++ decodeUtf8 :: ShortByteString -> LText+ decodeUtf8 = decodeUtf8 . fromShort+ {-# INLINE decodeUtf8 #-}++ decodeUtf8Strict :: ShortByteString -> Either T.UnicodeException LText+ decodeUtf8Strict = decodeUtf8Strict . fromShort+ {-# INLINE decodeUtf8Strict #-}++-- | Type class for converting other strings to 'T.Text'.+class ToText a where+ toText :: a -> Text++instance ToText String where+ toText :: String -> Text+ toText = T.pack+ {-# INLINE toText #-}++instance ToText Text where+ toText :: Text -> Text+ toText = id+ {-# INLINE toText #-}++instance ToText LText where+ toText :: LText -> Text+ toText = LT.toStrict+ {-# INLINE toText #-}++{- | ⚠️__CAUTION__⚠️ This instance is for custom error display only.++You should always specify encoding of bytes explicitly.++In case it is used by mistake, the user will see the following:++>>> toText ("some string" :: ByteString)+...+... Type 'ByteString' doesn't have instance of 'ToText'.+ Use 'decodeUtf8' or 'decodeUtf8Strict' to convert from UTF-8:+ decodeUtf8 :: ByteString -> Text+ decodeUtf8Strict :: ByteString -> Either UnicodeException Text+...++@since 0.6.0.0+-}+instance EncodingError ToText "ByteString" "Text" => ToText ByteString where+ toText :: ByteString -> Text+ toText = error "Unreachable ByteString instance of ToText"++{- | ⚠️__CAUTION__⚠️ This instance is for custom error display only.++You should always specify encoding of bytes explicitly.++In case it is used by mistake, the user will see the following:++>>> toText ("some string" :: LByteString)+...+... Type 'LByteString' doesn't have instance of 'ToText'.+ Use 'decodeUtf8' or 'decodeUtf8Strict' to convert from UTF-8:+ decodeUtf8 :: LByteString -> Text+ decodeUtf8Strict :: LByteString -> Either UnicodeException Text+...++@since 0.6.0.0+-}+instance EncodingError ToText "LByteString" "Text" => ToText LByteString where+ toText :: LByteString -> Text+ toText = error "Unreachable LByteString instance of ToText"++{- | ⚠️__CAUTION__⚠️ This instance is for custom error display only.++You should always specify encoding of bytes explicitly.++In case it is used by mistake, the user will see the following:++>>> toText ("some string" :: ShortByteString)+...+... Type 'ShortByteString' doesn't have instance of 'ToText'.+ Use 'decodeUtf8' or 'decodeUtf8Strict' to convert from UTF-8:+ decodeUtf8 :: ShortByteString -> Text+ decodeUtf8Strict :: ShortByteString -> Either UnicodeException Text+...++@since 0.6.0.0+-}+instance EncodingError ToText "ShortByteString" "Text" => ToText ShortByteString where+ toText :: ShortByteString -> Text+ toText = error "Unreachable ShortByteString instance of ToText"++-- | Type class for converting other strings to 'LT.Text'.+class ToLText a where+ toLText :: a -> LText++instance ToLText String where+ toLText :: String -> LText+ toLText = LT.pack+ {-# INLINE toLText #-}++instance ToLText Text where+ toLText :: Text -> LText+ toLText = LT.fromStrict+ {-# INLINE toLText #-}++instance ToLText LT.Text where+ toLText :: LText -> LText+ toLText = id+ {-# INLINE toLText #-}++{- | ⚠️__CAUTION__⚠️ This instance is for custom error display only.++You should always specify encoding of bytes explicitly.++In case it is used by mistake, the user will see the following:++>>> toLText ("some string" :: ByteString)+...+... Type 'ByteString' doesn't have instance of 'ToLText'.+ Use 'decodeUtf8' or 'decodeUtf8Strict' to convert from UTF-8:+ decodeUtf8 :: ByteString -> LText+ decodeUtf8Strict :: ByteString -> Either UnicodeException LText+...++@since 0.6.0.0+-}+instance EncodingError ToLText "ByteString" "LText" => ToLText ByteString where+ toLText :: ByteString -> LText+ toLText = error "Unreachable ByteString instance of ToLText"++{- | ⚠️__CAUTION__⚠️ This instance is for custom error display only.++You should always specify encoding of bytes explicitly.++In case it is used by mistake, the user will see the following:++>>> toLText ("some string" :: LByteString)+...+... Type 'LByteString' doesn't have instance of 'ToLText'.+ Use 'decodeUtf8' or 'decodeUtf8Strict' to convert from UTF-8:+ decodeUtf8 :: LByteString -> LText+ decodeUtf8Strict :: LByteString -> Either UnicodeException LText+...++@since 0.6.0.0+-}+instance EncodingError ToLText "LByteString" "LText" => ToLText LByteString where+ toLText :: LByteString -> LText+ toLText = error "Unreachable LByteString instance of ToLText"++{- | ⚠️__CAUTION__⚠️ This instance is for custom error display only.++You should always specify encoding of bytes explicitly.++In case it is used by mistake, the user will see the following:++>>> toLText ("some string" :: ShortByteString)+...+... Type 'ShortByteString' doesn't have instance of 'ToLText'.+ Use 'decodeUtf8' or 'decodeUtf8Strict' to convert from UTF-8:+ decodeUtf8 :: ShortByteString -> LText+ decodeUtf8Strict :: ShortByteString -> Either UnicodeException LText+...++@since 0.6.0.0+-}+instance EncodingError ToLText "ShortByteString" "LText" => ToLText ShortByteString where+ toLText :: ShortByteString -> LText+ toLText = error "Unreachable ShortByteString instance of ToLText"++-- | Type class for converting other strings to 'String'.+class ToString a where+ toString :: a -> String++instance ToString String where+ toString :: String -> String+ toString = id+ {-# INLINE toString #-}++instance ToString Text where+ toString :: Text -> String+ toString = T.unpack+ {-# INLINE toString #-}++instance ToString LText where+ toString :: LText -> String+ toString = LT.unpack+ {-# INLINE toString #-}++{- | ⚠️__CAUTION__⚠️ This instance is for custom error display only.++You should always specify encoding of bytes explicitly.++In case it is used by mistake, the user will see the following:++>>> toString ("some string" :: ByteString)+...+... Type 'ByteString' doesn't have instance of 'ToString'.+ Use 'decodeUtf8' or 'decodeUtf8Strict' to convert from UTF-8:+ decodeUtf8 :: ByteString -> String+ decodeUtf8Strict :: ByteString -> Either UnicodeException String+...++@since 0.6.0.0+-}+instance EncodingError ToString "ByteString" "String" => ToString ByteString where+ toString :: ByteString -> String+ toString = error "Unreachable ByteString instance of ToString"++{- | ⚠️__CAUTION__⚠️ This instance is for custom error display only.++You should always specify encoding of bytes explicitly.++In case it is used by mistake, the user will see the following:++>>> toString ("some string" :: LByteString)+...+... Type 'LByteString' doesn't have instance of 'ToString'.+ Use 'decodeUtf8' or 'decodeUtf8Strict' to convert from UTF-8:+ decodeUtf8 :: LByteString -> String+ decodeUtf8Strict :: LByteString -> Either UnicodeException String+...++@since 0.6.0.0+-}+instance EncodingError ToString "LByteString" "String" => ToString LByteString where+ toString :: LByteString -> String+ toString = error "Unreachable LByteString instance of ToString"++{- | ⚠️__CAUTION__⚠️ This instance is for custom error display only.++You should always specify encoding of bytes explicitly.++In case it is used by mistake, the user will see the following:++>>> toString ("some string" :: ShortByteString)+...+... Type 'ShortByteString' doesn't have instance of 'ToString'.+ Use 'decodeUtf8' or 'decodeUtf8Strict' to convert from UTF-8:+ decodeUtf8 :: ShortByteString -> String+ decodeUtf8Strict :: ShortByteString -> Either UnicodeException String+...++@since 0.6.0.0+-}+instance EncodingError ToString "ShortByteString" "String" => ToString ShortByteString where+ toString :: ShortByteString -> String+ toString = error "Unreachable ShortByteString instance of ToString"++-- | Helper type family to produce error messages+type family EncodingError+ (c :: Type -> Constraint)+ (from :: Symbol)+ (to :: Symbol)+ :: Constraint+ where+ EncodingError c from to = TypeError+ ( 'Error.Text "Type '" ':<>: 'Error.Text from ':<>: 'Error.Text "' doesn't have instance of '"+ ':<>: 'ShowType c ':<>: 'Error.Text "'."+ ':$$: 'Error.Text "Use 'decodeUtf8' or 'decodeUtf8Strict' to convert from UTF-8:"+ ':$$: 'Error.Text " decodeUtf8 :: " ':<>: 'Error.Text from+ ':<>: 'Error.Text " -> " ':<>: 'Error.Text to+ ':$$: 'Error.Text " decodeUtf8Strict :: " ':<>: 'Error.Text from+ ':<>: 'Error.Text " -> Either UnicodeException " ':<>: 'Error.Text to+ )++{- | Version of 'Text.Read.readEither' that returns 'Text' in case of the parse+error.++>>> readEither @Int "123"+Right 123+>>> readEither @Int "aa"+Left "Prelude.read: no parse"+-}+readEither :: (Read a) => String -> Either Text a+readEither = first toText . Text.Read.readEither+{-# INLINEABLE readEither #-}++{- | Generalized version of 'Prelude.show'. Unlike 'Prelude.show' this function+is polymorphic in its result type. This makes it more convenient to work with+data types like 'Incipit.String.Reexport.Text' or 'ByteString'. However, if you+pass the result of 'show' to a function that expects polymorphic argument, this+can break type inference, so use @-XTypeApplications@ to specify the textual+type explicitly.++>>> show (42 :: Int)+"42"+>>> show (42 :: Double)+"42.0"+>>> print (show @Text True)+"True"+-}+show :: ∀ b a . (Show.Show a, IsString b) => a -> b+show x = fromString (Show.show x)+{-# INLINE show #-}+{-# SPECIALIZE show :: Show.Show a => a -> Text #-}+{-# SPECIALIZE show :: Show.Show a => a -> LText #-}+{-# SPECIALIZE show :: Show.Show a => a -> ByteString #-}+{-# SPECIALIZE show :: Show.Show a => a -> LByteString #-}+{-# SPECIALIZE show :: Show.Show a => a -> String #-}++{- | Type class for lazy-strict conversions.++@since 0.1.0+-}+class LazyStrict l s | l -> s, s -> l where+ toLazy :: s -> l+ toStrict :: l -> s++-- | Alias for 'toStrict' function.+fromLazy :: LazyStrict l s => l -> s+fromLazy = toStrict+{-# INLINE fromLazy #-}+{-# SPECIALIZE fromLazy :: LByteString -> ByteString #-}+{-# SPECIALIZE fromLazy :: LText -> Text #-}++-- | Alias for 'toLazy' function.+fromStrict :: LazyStrict l s => s -> l+fromStrict = toLazy+{-# INLINE fromStrict #-}+{-# SPECIALIZE fromStrict :: ByteString -> LByteString #-}+{-# SPECIALIZE fromStrict :: Text -> LText #-}++instance LazyStrict LByteString ByteString where+ toLazy :: ByteString -> LByteString+ toLazy = LB.fromStrict+ {-# INLINE toLazy #-}++ toStrict :: LByteString -> ByteString+ toStrict = LB.toStrict+ {-# INLINE toStrict #-}++instance LazyStrict LText Text where+ toLazy :: Text -> LText+ toLazy = LT.fromStrict+ {-# INLINE toLazy #-}++ toStrict :: LText -> Text+ toStrict = LT.toStrict+ {-# INLINE toStrict #-}
+ lib/Incipit/String/Reexport.hs view
@@ -0,0 +1,209 @@+{-# options_haddock prune #-}++{- |+Copyright: (c) 2016 Stephen Diehl+ (c) 2016-2018 Serokell+ (c) 2018-2021 Kowainik+SPDX-License-Identifier: MIT+Maintainer: Kowainik <xrom.xkov@gmail.com>+Stability: Stable+Portability: Portable++Reexports functions to work with 'Data.Text.Text', 'ByteString' and+'ShortByteString' types.+-}++module Incipit.String.Reexport+ ( -- * String+ module Data.String+ , module Text.Read++ -- * Text+ , Text+ , lines+ , unlines+ , words+ , unwords+ , module Data.Text.Encoding+ , module Data.Text.Encoding.Error++ -- * ByteString+ , ByteString++ -- * ShortByteString+ , ShortByteString+ , toShort+ , fromShort+ ) where++import Data.ByteString (ByteString)+import Data.ByteString.Short (ShortByteString, fromShort, toShort)+import Data.String (IsString (..), String)+import qualified Data.Text as Text+import Data.Text (Text)+import Data.Text.Encoding (decodeUtf8', decodeUtf8With)+import Data.Text.Encoding.Error (OnDecodeError, OnError, UnicodeException, lenientDecode, strictDecode)+import GHC.TypeLits (ErrorMessage (..), Symbol, TypeError)+import Text.Read (Read, readMaybe, reads)++import Incipit.Base (Constraint, Type)+++-- $setup+-- >>> import Relude++-- | For tracking usage of Text instead of String+type IsText+ (t :: Type) -- Textual type, e.g. Text, String+ (fun :: Symbol) -- Function name+ = (t ~ Text, CheckText t fun)++type family CheckText (t :: Type) (fun :: Symbol) :: Constraint where+ CheckText Text _ = ()+ CheckText String fun = TypeError+ ( 'Text "'" ':<>: 'Text fun ':<>: 'Text "' works with 'Text', not 'String'."+ ':$$: 'Text "Possible fixes:"+ ':$$: 'Text " 1. Make sure OverloadedStrings extension is enabled."+ ':$$: 'Text " 2. Apply 'toText' to a single value."+ ':$$: 'Text " 3. Apply 'map toText' to the list value."+ )+ CheckText a fun = TypeError+ ( 'Text "'" ':<>: 'Text fun ':<>: 'Text "' works with 'Text'"+ ':$$: 'Text "But given: '" ':<>: 'ShowType a ':<>: 'Text "'"+ )++{- | 'lines' takes 'Data.Text.Text' and splits it into the list by lines.++Actual type of this function is the following:++@+lines :: 'Data.Text.Text' -> ['Data.Text.Text']+@++but it was given a more complex type to provide friendlier compile time errors.++>>> lines ""+[]+>>> lines "one line"+["one line"]+>>> lines "line 1\nline 2"+["line 1","line 2"]+>>> lines ("string line" :: String)+...+... 'lines' works with 'Text', not 'String'.+ Possible fixes:+ 1. Make sure OverloadedStrings extension is enabled.+ 2. Apply 'toText' to a single value.+ 3. Apply 'map toText' to the list value.+...+>>> lines True+...+... 'lines' works with 'Text'+ But given: 'Bool'+...+-}+lines :: IsText t "lines" => t -> [t]+lines = Text.lines+{-# INLINE lines #-}++{- | 'unlines' takes list of 'Data.Text.Text' values and joins them with line separator.++Actual type of this function is the following:++@+unlines :: ['Data.Text.Text'] -> 'Data.Text.Text'+@++but it was given a more complex type to provide friendlier compile time errors.++>>> unlines []+""+>>> unlines ["line 1"]+"line 1\n"+>>> unlines ["first line", "second line"]+"first line\nsecond line\n"+>>> unlines (["line 1", "line 2"] :: [String])+...+... 'unlines' works with 'Text', not 'String'.+ Possible fixes:+ 1. Make sure OverloadedStrings extension is enabled.+ 2. Apply 'toText' to a single value.+ 3. Apply 'map toText' to the list value.+...+>>> unlines [True, False]+...+... 'unlines' works with 'Text'+ But given: 'Bool'+...+-}+unlines :: IsText t "unlines" => [t] -> t+unlines = Text.unlines+{-# INLINE unlines #-}++{- | 'words' takes 'Data.Text.Text' and splits it into the list by words.++Actual type of this function is the following:++@+words :: 'Data.Text.Text' -> ['Data.Text.Text']+@++but it was given a more complex type to provide friendlier compile time errors.++>>> words ""+[]+>>> words "one line"+["one","line"]+>>> words " >_< "+[">_<"]+>>> words ("string words" :: String)+...+... 'words' works with 'Text', not 'String'.+ Possible fixes:+ 1. Make sure OverloadedStrings extension is enabled.+ 2. Apply 'toText' to a single value.+ 3. Apply 'map toText' to the list value.+...+>>> words True+...+... 'words' works with 'Text'+ But given: 'Bool'+...+-}+words :: IsText t "words" => t -> [t]+words = Text.words+{-# INLINE words #-}++{- | 'unwords' takes list of 'Data.Text.Text' values and joins them with space character.++Actual type of this function is the following:++@+unwords :: ['Data.Text.Text'] -> 'Data.Text.Text'+@++but it was given a more complex type to provide friendlier compile time errors.++>>> unwords []+""+>>> unwords ["singleWord"]+"singleWord"+>>> unwords ["word", "another"]+"word another"+>>> unwords (["word", "another"] :: [String])+...+... 'unwords' works with 'Text', not 'String'.+ Possible fixes:+ 1. Make sure OverloadedStrings extension is enabled.+ 2. Apply 'toText' to a single value.+ 3. Apply 'map toText' to the list value.+...+>>> unwords [True, False]+...+... 'unwords' works with 'Text'+ But given: 'Bool'+...+-}+unwords :: IsText t "unwords" => [t] -> t+unwords = Text.unwords+{-# INLINE unwords #-}
+ readme.md view
@@ -0,0 +1,5 @@+This library is part of [incipit], a set of `Prelude` modules for the [Polysemy] ecosystem.+It contains the reexports from `base` that are inherited by the other two packages.++[incipit]: https://hackage.haskell.org/package/incipit+[Polysemy]: https://hackage.haskell.org/package/polysemy