string-isos (empty) → 0.1.0.0
raw patch · 6 files changed
+335/−0 lines, 6 filesdep +basedep +bytestringdep +mono-traversablesetup-changed
Dependencies added: base, bytestring, mono-traversable, safe, text, type-iso
Files
- ChangeLog.md +5/−0
- LICENSE +30/−0
- Setup.hs +2/−0
- src/Text/Foldable.hs +136/−0
- src/Text/Isomorphic.hs +127/−0
- string-isos.cabal +35/−0
+ ChangeLog.md view
@@ -0,0 +1,5 @@+# Revision history for string-isos++## 0.1.0.0 -- YYYY-mm-dd++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2018, Isaac Shapira++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * 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.++ * Neither the name of Isaac Shapira nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++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+OWNER 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
+ src/Text/Foldable.hs view
@@ -0,0 +1,136 @@+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++{-|+Many of the common things we want to do with String like structures are just properties of MonoFoldable.+This module provides a classes for MonoFoldables that contain Char as Stringlike structures.++The motivation here is to have re-usable functions abstracted over common things we get from Foldable.+The reason we can't just use the mono-traversable package, is that it's ByteString instances are MonoFoldables containing @Word8@, an the goal here is to normalize the API around Char.++For example:++@+ isFiveChars :: FoldableString s => s -> Bool+ isFiveChars s = length s == 5+@++Which will work with all 5 string types++The motivation here is to have re-usable functions abstracted over common things we get from Foldable.++For example:++@+ isFiveChars :: FoldableString s => s -> Bool+ isFiveChars s = length s == 5+@++Which will work with all 5 string types.+.++-}++module Text.Foldable+ ( module Data.MonoTraversable+ , FunctorString (..)+ , FoldableString (..)+ , TraverseString (..)) where++import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BSC+import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString.Lazy.Char8 as BLC+import qualified Data.Char as C+import Data.MonoTraversable+import qualified Data.String as S+import qualified Data.Text as TS+import qualified Data.Text.Encoding as TSE+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Encoding as TLE++import Text.Isomorphic++{-| MonoFunctor containing Char -}+class FunctorString s where+ map :: (Char -> Char) -> s -> s+ default map :: (MonoFunctor s, Element s ~ Char) => (Char -> Char) -> s -> s+ map = omap++instance FunctorString String+instance FunctorString TS.Text+instance FunctorString TL.Text+instance FunctorString BS.ByteString where map = BSC.map+instance FunctorString BL.ByteString where map = BLC.map++{-| MonoFoldable containing Char -}+class FoldableString s where+ foldMap :: (Char -> s) -> s -> s+ default foldMap :: (MonoFoldable s, Element s ~ Char, Monoid m) => (Char -> m) -> s -> m+ foldMap = ofoldMap+ foldr :: (Char -> a -> a) -> a -> s -> a+ default foldr :: (MonoFoldable s, Element s ~ Char) => (Char -> a -> a) -> a -> s -> a+ foldr = ofoldr+ foldl' :: (a -> Char -> a) -> a -> s -> a+ default foldl' :: (MonoFoldable s, Element s ~ Char) => (a -> Char -> a) -> a -> s -> a+ foldl' = ofoldl'+ all :: (Char -> Bool) -> s -> Bool+ default all :: (MonoFoldable s, Element s ~ Char) => (Char -> Bool) -> s -> Bool+ all = oall+ any :: (Char -> Bool) -> s -> Bool+ default any :: (MonoFoldable s, Element s ~ Char) => (Char -> Bool) -> s -> Bool+ any = oany+ null :: s -> Bool+ default null :: (MonoFoldable s) => s -> Bool+ null = onull+ length :: s -> Int+ default length :: (MonoFoldable s) => s -> Int+ length = olength+ elem :: Char -> s -> Bool+ default elem :: (MonoFoldable s, Element s ~ Char) => Char -> s -> Bool+ elem = oelem+ maximum :: s -> Char+ default maximum :: (MonoFoldable s, Element s ~ Char) => s -> Char+ maximum = maximumEx+ minimum :: s -> Char+ default minimum :: (MonoFoldable s, Element s ~ Char) => s -> Char+ minimum = minimumEx++instance FoldableString String+instance FoldableString TS.Text+instance FoldableString TL.Text+instance FoldableString BS.ByteString where+ foldMap = BSC.concatMap+ foldr = BSC.foldr+ foldl' = BSC.foldl'+ all = BSC.all+ any = BSC.any+ elem = BSC.elem+ maximum = BSC.maximum+ minimum = BSC.minimum+instance FoldableString BL.ByteString where+ foldMap = BLC.concatMap+ foldr = BLC.foldr+ foldl' = BLC.foldl'+ all = BLC.all+ any = BLC.any+ elem = BLC.elem+ maximum = BLC.maximum+ minimum = BLC.minimum++{-| MonoTraversable containing Char -}+class (FunctorString s, FoldableString s) => TraverseString s where+ traverse :: Applicative f => (Char -> f Char) -> s -> f s+ default traverse :: (MonoTraversable s, Element s ~ Char, Applicative f) => (Char -> f Char) -> s -> f s+ traverse = otraverse++instance TraverseString String+instance TraverseString TS.Text+instance TraverseString TL.Text+instance TraverseString BS.ByteString where+ traverse f = fmap to . Prelude.traverse f . (to @ BS.ByteString @ String)+instance TraverseString BL.ByteString where+ traverse f = fmap to . Prelude.traverse f . (to @ BL.ByteString @ String)
+ src/Text/Isomorphic.hs view
@@ -0,0 +1,127 @@+{-# LANGUAGE ExplicitForAll #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE UndecidableInstances #-}++{-| Assuming UTF8 encoding the following types are isomorphic++ - Data.ByteString.Lazy.ByteString+ - Data.ByteString.ByteString+ - Data.Text.Lazy.Text+ - Data.Text.Text+ - String++Yet working with them and converting is a pain!++This package exposes this 5 way isomorphism to make conversion easy.+-}+module Text.Isomorphic+ ( module Data.Types.Injective+ , module Data.Types.Isomorphic+ , as, as2, as3, as4 ) where++import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BSC+import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString.Lazy.Char8 as BLC+import qualified Data.Char as C+import qualified Data.String as S+import qualified Data.Text as TS+import qualified Data.Text.Encoding as TSE+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Encoding as TLE+import Data.Types.Injective+import Data.Types.Isomorphic++instance {-# OVERLAPPABLE #-} S.IsString s => Injective String s where to = S.fromString+++instance Injective BS.ByteString String where+ to = BSC.unpack+ {-# INLINE to #-}+instance Injective String BS.ByteString where+ to = BSC.pack+ {-# INLINE to #-}+instance Iso String BS.ByteString+instance Iso BS.ByteString String++instance Injective BL.ByteString String where+ to = BLC.unpack+ {-# INLINE to #-}+instance Injective String BL.ByteString where+ to = BLC.pack+ {-# INLINE to #-}+instance Iso String BL.ByteString+instance Iso BL.ByteString String++instance Injective TS.Text BS.ByteString where+ to = TSE.encodeUtf8+ {-# INLINE to #-}+instance Injective BS.ByteString TS.Text where+ to = TSE.decodeUtf8+ {-# INLINE to #-}+instance Iso TS.Text BS.ByteString+instance Iso BS.ByteString TS.Text++instance Injective TS.Text BL.ByteString where+ to = BL.fromStrict . to+ {-# INLINE to #-}+instance Injective BL.ByteString TS.Text where+ to = to . BL.toStrict+ {-# INLINE to #-}+instance Iso TS.Text BL.ByteString+instance Iso BL.ByteString TS.Text++instance Injective TL.Text BS.ByteString where+ to = BL.toStrict . to+ {-# INLINE to #-}+instance Injective BS.ByteString TL.Text where+ to = to . BL.fromStrict+ {-# INLINE to #-}+instance Iso TL.Text BS.ByteString+instance Iso BS.ByteString TL.Text++instance Injective TL.Text BL.ByteString where+ to = TLE.encodeUtf8+ {-# INLINE to #-}+instance Injective BL.ByteString TL.Text where+ to = TLE.decodeUtf8+ {-# INLINE to #-}+instance Iso TL.Text BL.ByteString+instance Iso BL.ByteString TL.Text++instance Injective BS.ByteString BL.ByteString where+ to = BL.fromStrict+ {-# INLINE to #-}+instance Injective BL.ByteString BS.ByteString where+ to = BL.toStrict+ {-# INLINE to #-}+instance Iso BS.ByteString BL.ByteString+instance Iso BL.ByteString BS.ByteString++{-| This is useful for any iso, but in the case of string like stuff.+ You can now work with a function from one string type, while not having to do+ any conversion.++@+ f :: ByteString -> ByteString+ a :: Text+ as f a :: Text+@+-}+as :: forall a b. (Iso a b, Iso b a) => (a -> a) -> b -> b+as f = from . f . to+{-# INLINABLE as #-}++{-| Like @liftA2@ -}+as2 :: forall a b. (Iso a b, Iso b a) => (a -> a -> a) -> b -> b -> b+as2 f x y = from $ f (to x) (to y)++{-| Like @liftA3@ -}+as3 :: forall a b. (Iso a b, Iso b a) => (a -> a -> a -> a) -> b -> b -> b -> b+as3 f x y z = from $ f (to x) (to y) (to z)++{-| Like @liftA4@ -}+as4 :: forall a b. (Iso a b, Iso b a) => (a -> a -> a -> a -> a) -> b -> b -> b -> b -> b+as4 f w x y z = from $ f (to w) (to x) (to y) (to z)
+ string-isos.cabal view
@@ -0,0 +1,35 @@+-- Initial string-isos.cabal generated by cabal init. For further+-- documentation, see http://haskell.org/cabal/users-guide/++name: string-isos+version: 0.1.0.0+synopsis: Tools for working with isomorphisms of strings+description: Haskell has 5 common string types, Text, Lazy Text, ByteString, Lazy ByteString, and String ([Char]). Assuming utf8 encoding, we can make the pain of these conflicts much less via polymorphism.+license: BSD3+license-file: LICENSE+author: Isaac Shapira+maintainer: fresheyeball@gmail.com+-- copyright:+category: Text+build-type: Simple+extra-source-files: ChangeLog.md+cabal-version: >=1.10++source-repository head+ type: git+ location: https://gitlab.com/fresheyeball/String-Iso.git++library+ exposed-modules: Text.Isomorphic+ Text.Foldable+ -- other-modules:+ -- other-extensions:+ ghc-options: -Wwarn+ build-depends: base >= 4.9 && < 4.10.2+ , text >= 1.2.2 && < 1.3+ , bytestring >= 0.10.8 && < 0.11+ , mono-traversable >= 1.0.2 && < 1.1+ , type-iso >= 0.1.0 && < 0.2+ , safe >= 0.3.15 && < 0.4+ hs-source-dirs: src+ default-language: Haskell2010