string-variants 0.2.2.0 → 0.3.0.0
raw patch · 7 files changed
+68/−8 lines, 7 files
Files
- CHANGELOG.md +9/−0
- src/Data/StringVariants/NonEmptyText.hs +11/−1
- src/Data/StringVariants/NonEmptyText/Internal.hs +11/−2
- src/Data/StringVariants/NullableNonEmptyText.hs +27/−2
- src/Data/StringVariants/Prose.hs +1/−0
- src/Data/StringVariants/Prose/Internal.hs +7/−1
- string-variants.cabal +2/−2
CHANGELOG.md view
@@ -1,5 +1,14 @@ # Changelog +## [0.3.0.0] - 2023-10-24++- Remove incorrect `Semigroup` instance for `NonEmptyText`++## [0.2.2.1] - 2023-06-20++- Add support for `aeson-2.2.0.0`.+- When built with `aeson >=2.2.0.0`, record fields with type `NullableNonEmptyText` will be omittable.+ ## [0.2.2.0] - 2023-02-10 - Add `proseFromNonEmptyText` to create `Prose` from `NonEmptyText`.
src/Data/StringVariants/NonEmptyText.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeOperators #-} {-# OPTIONS_GHC -Wno-redundant-constraints #-}@@ -13,6 +14,7 @@ -- * Construction mkNonEmptyText, mkNonEmptyTextWithTruncate,+ IsNonEmptyText, literalNonEmptyText, unsafeMkNonEmptyText, compileNonEmptyText,@@ -73,7 +75,15 @@ where errorMessage = fail $ "Invalid NonEmptyText. Needs to be < " ++ show (n + 1) ++ " characters, and not entirely whitespace: " ++ s -literalNonEmptyText :: forall (s :: Symbol) (n :: Nat). (KnownSymbol s, KnownNat n, SymbolNonEmpty s, SymbolWithNoSpaceAround s, SymbolNoLongerThan s n) => NonEmptyText n+type IsNonEmptyText n s =+ ( KnownSymbol s+ , KnownNat n+ , SymbolNonEmpty s+ , SymbolWithNoSpaceAround s+ , SymbolNoLongerThan s n+ )++literalNonEmptyText :: forall (s :: Symbol) (n :: Nat). IsNonEmptyText n s => NonEmptyText n literalNonEmptyText = NonEmptyText (T.pack (symbolVal (Proxy @s))) convertEmptyTextToNothing :: Text -> Maybe Text
src/Data/StringVariants/NonEmptyText/Internal.hs view
@@ -22,7 +22,7 @@ import Data.Text (Text) import Data.Text qualified as T import GHC.Generics (Generic)-import GHC.TypeLits (KnownNat, Nat, natVal, type (<=))+import GHC.TypeLits (ErrorMessage (..), KnownNat, Nat, TypeError, natVal, type (<=)) import Language.Haskell.TH.Quote import Language.Haskell.TH.Syntax (Lift (..), TyLit (..), Type (..)) import Test.QuickCheck@@ -31,7 +31,7 @@ -- | Non Empty Text, requires the input is between 1 and @n@ chars and not just whitespace. newtype NonEmptyText (n :: Nat) = NonEmptyText Text deriving stock (Generic, Show, Read, Lift)- deriving newtype (Eq, Ord, ToJSON, Semigroup, MonoFoldable)+ deriving newtype (Eq, Ord, ToJSON, MonoFoldable) type instance Element (NonEmptyText _n) = Char @@ -73,6 +73,15 @@ -- Mostly alphanumeric characters, all human readable str <- replicateM size $ elements ['0' .. 'z'] pure $ T.pack str++instance+ TypeError+ ( 'Text "An instance of 'Semigroup (NonEmptyText n)' would violate the "+ ':<>: 'Text "length guarantees."+ ':$$: 'Text "Please use '(<>|)' or 'concatWithSpace' to combine the values."+ )+ => Semigroup (NonEmptyText n) where+ (<>) = error "unreachable" mkNonEmptyText :: forall n. (KnownNat n, 1 <= n) => Text -> Maybe (NonEmptyText n) mkNonEmptyText t
src/Data/StringVariants/NullableNonEmptyText.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-}@@ -9,6 +11,7 @@ -- * Constructing mkNonEmptyTextWithTruncate, compileNullableNonEmptyText,+ IsNullableNonEmptyText, literalNullableNonEmptyText, mkNullableNonEmptyText, parseNullableNonEmptyText,@@ -59,7 +62,7 @@ -- use 'nullableNonEmptyTextToMaybeNonEmptyText'. newtype NullableNonEmptyText n = NullableNonEmptyText (Maybe (NonEmptyText n)) deriving stock (Generic, Show, Read, Lift)- deriving newtype (Eq, ToJSON)+ deriving newtype (Eq) mkNullableNonEmptyText :: forall n. (KnownNat n, 1 <= n) => Text -> Maybe (NullableNonEmptyText n) mkNullableNonEmptyText t@@ -72,6 +75,16 @@ isNullNonEmptyText :: NullableNonEmptyText n -> Bool isNullNonEmptyText = (== nullNonEmptyText) +instance ToJSON (NullableNonEmptyText n) where+ toJSON (NullableNonEmptyText t) = toJSON t++ toEncoding (NullableNonEmptyText t) = toEncoding t++#if MIN_VERSION_aeson(2,2,0)+ omitField (NullableNonEmptyText Nothing) = True+ omitField _ = False+#endif+ instance (KnownNat n, 1 <= n) => FromJSON (NullableNonEmptyText n) where parseJSON = \case J.String t -> case mkNullableNonEmptyText t of@@ -80,6 +93,10 @@ J.Null -> pure $ NullableNonEmptyText Nothing x -> fail $ "Data/StringVariants/NullableNonEmptyText.hs: When trying to parse a NullableNonEmptyText, expected a String or Null, but received: " ++ show x +#if MIN_VERSION_aeson(2,2,0)+ omittedField = Just (NullableNonEmptyText Nothing)+#endif+ parseNullableNonEmptyText :: (KnownNat n, 1 <= n) => Text -> J.Object -> J.Parser (NullableNonEmptyText n) parseNullableNonEmptyText fieldName obj = obj .:? J.fromText fieldName .!= nullNonEmptyText @@ -119,6 +136,14 @@ where errorMessage = fail $ "Invalid NullableNonEmptyText. Needs to be < " ++ show (n + 1) ++ " characters, and not entirely whitespace: " ++ s +type IsNullableNonEmptyText n s =+ ( KnownSymbol s+ , KnownNat n+ , SymbolNonEmpty s+ , SymbolWithNoSpaceAround s+ , SymbolNoLongerThan s n+ )+ -- | This requires the text to be non-empty. For the empty text just use the constructor `NullableNonEmptyText Nothing`-literalNullableNonEmptyText :: forall (s :: Symbol) (n :: Nat). (KnownSymbol s, KnownNat n, SymbolNonEmpty s, SymbolWithNoSpaceAround s, SymbolNoLongerThan s n) => NullableNonEmptyText n+literalNullableNonEmptyText :: forall (s :: Symbol) (n :: Nat). IsNullableNonEmptyText n s => NullableNonEmptyText n literalNullableNonEmptyText = NullableNonEmptyText (Just (literalNonEmptyText @s @n))
src/Data/StringVariants/Prose.hs view
@@ -3,6 +3,7 @@ ( Prose, mkProse, compileProse,+ IsProse, literalProse, proseToText, proseFromNonEmptyText
src/Data/StringVariants/Prose/Internal.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE TemplateHaskell #-} -- GHC considers the constraints for the prose symbol redundant.@@ -65,7 +66,12 @@ msg s = "Invalid Prose: " <> s <> ". Make sure you aren't wrapping the text in quotes." -literalProse :: forall (s :: Symbol). (KnownSymbol s, SymbolWithNoSpaceAround s) => Prose+type IsProse s =+ ( KnownSymbol s+ , SymbolWithNoSpaceAround s+ )++literalProse :: forall (s :: Symbol). IsProse s => Prose literalProse = Prose (T.pack (symbolVal (Proxy @s))) proseToText :: Prose -> Text
string-variants.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.35.0.+-- This file has been generated from package.yaml by hpack version 0.35.2. -- -- see: https://github.com/sol/hpack name: string-variants-version: 0.2.2.0+version: 0.3.0.0 synopsis: Constrained text newtypes description: See README at <https://github.com/MercuryTechnologies/string-variants#readme>. category: Data