module Language.Fluent.Value where import Data.List.NonEmpty (NonEmpty) import Data.Scientific (Scientific, fromFloatDigits) import Data.String (IsString (..)) import Data.Text (Text) import Data.Text qualified as Text import Data.Time (UTCTime) import Language.Fluent.Locale (Locale (..)) import Language.Fluent.Number (NumberOptions, numberOptions) import Language.Fluent.Time (TimeOptions, timeOptions) import Prelude data CustomValue = forall v. (Value v) => CustomValue v class Value v where value :: v -> SomeValue format :: (Locale l) => NonEmpty l -> v -> Either String Text format NonEmpty l locale = NonEmpty l -> SomeValue -> Either String Text forall l. Locale l => NonEmpty l -> SomeValue -> Either String Text forall v l. (Value v, Locale l) => NonEmpty l -> v -> Either String Text format NonEmpty l locale (SomeValue -> Either String Text) -> (v -> SomeValue) -> v -> Either String Text forall b c a. (b -> c) -> (a -> b) -> a -> c . v -> SomeValue forall v. Value v => v -> SomeValue value data SomeValue = StringValue Text | NumberValue Scientific NumberOptions | TimeValue UTCTime TimeOptions | SomeValue CustomValue instance Value Text where value :: Text -> SomeValue value = Text -> SomeValue StringValue format :: forall l. Locale l => NonEmpty l -> Text -> Either String Text format NonEmpty l _ = Text -> Either String Text forall a b. b -> Either a b Right instance Value String where value :: String -> SomeValue value = Text -> SomeValue StringValue (Text -> SomeValue) -> (String -> Text) -> String -> SomeValue forall b c a. (b -> c) -> (a -> b) -> a -> c . String -> Text Text.pack instance Value Scientific where value :: Scientific -> SomeValue value = (Scientific -> NumberOptions -> SomeValue) -> NumberOptions -> Scientific -> SomeValue forall a b c. (a -> b -> c) -> b -> a -> c flip Scientific -> NumberOptions -> SomeValue NumberValue NumberOptions numberOptions instance Value Int where value :: Int -> SomeValue value = Scientific -> SomeValue forall v. Value v => v -> SomeValue value (Scientific -> SomeValue) -> (Int -> Scientific) -> Int -> SomeValue forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. (Integral a, Num b) => a -> b fromIntegral @Int @Scientific instance Value Integer where value :: Integer -> SomeValue value = Scientific -> SomeValue forall v. Value v => v -> SomeValue value (Scientific -> SomeValue) -> (Integer -> Scientific) -> Integer -> SomeValue forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. (Integral a, Num b) => a -> b fromIntegral @Integer @Scientific instance Value Word where value :: Word -> SomeValue value = Scientific -> SomeValue forall v. Value v => v -> SomeValue value (Scientific -> SomeValue) -> (Word -> Scientific) -> Word -> SomeValue forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. (Integral a, Num b) => a -> b fromIntegral @Word @Scientific instance Value Double where value :: Double -> SomeValue value = Scientific -> SomeValue forall v. Value v => v -> SomeValue value (Scientific -> SomeValue) -> (Double -> Scientific) -> Double -> SomeValue forall b c a. (b -> c) -> (a -> b) -> a -> c . Double -> Scientific forall a. RealFloat a => a -> Scientific fromFloatDigits instance Value UTCTime where value :: UTCTime -> SomeValue value = (UTCTime -> TimeOptions -> SomeValue) -> TimeOptions -> UTCTime -> SomeValue forall a b c. (a -> b -> c) -> b -> a -> c flip UTCTime -> TimeOptions -> SomeValue TimeValue TimeOptions timeOptions instance Value CustomValue where value :: CustomValue -> SomeValue value = CustomValue -> SomeValue SomeValue format :: forall l. Locale l => NonEmpty l -> CustomValue -> Either String Text format NonEmpty l locale (CustomValue v v) = NonEmpty l -> v -> Either String Text forall l. Locale l => NonEmpty l -> v -> Either String Text forall v l. (Value v, Locale l) => NonEmpty l -> v -> Either String Text format NonEmpty l locale v v instance IsString SomeValue where fromString :: String -> SomeValue fromString = String -> SomeValue forall v. Value v => v -> SomeValue value instance Show SomeValue where show :: SomeValue -> String show (StringValue Text t) = String "StringValue " String -> ShowS forall a. Semigroup a => a -> a -> a <> Text -> String Text.unpack Text t show (NumberValue Scientific n NumberOptions _) = String "NumberValue " String -> ShowS forall a. Semigroup a => a -> a -> a <> Scientific -> String forall a. Show a => a -> String show Scientific n show (TimeValue UTCTime t TimeOptions _) = String "TimeValue " String -> ShowS forall a. Semigroup a => a -> a -> a <> UTCTime -> String forall a. Show a => a -> String show UTCTime t show SomeValue{} = String "SomeValue" instance Value SomeValue where value :: SomeValue -> SomeValue value = SomeValue -> SomeValue forall a. a -> a id format :: forall l. Locale l => NonEmpty l -> SomeValue -> Either String Text format NonEmpty l locales (StringValue Text s) = NonEmpty l -> Text -> Either String Text forall l. Locale l => NonEmpty l -> Text -> Either String Text forall v l. (Value v, Locale l) => NonEmpty l -> v -> Either String Text format NonEmpty l locales Text s format NonEmpty l locales (NumberValue Scientific n NumberOptions o) = NonEmpty l -> Scientific -> NumberOptions -> Either String Text forall l. Locale l => NonEmpty l -> Scientific -> NumberOptions -> Either String Text formatNumber NonEmpty l locales Scientific n NumberOptions o format NonEmpty l locales (TimeValue UTCTime t TimeOptions o) = NonEmpty l -> UTCTime -> TimeOptions -> Either String Text forall l. Locale l => NonEmpty l -> UTCTime -> TimeOptions -> Either String Text formatTime NonEmpty l locales UTCTime t TimeOptions o format NonEmpty l locales (SomeValue CustomValue v) = NonEmpty l -> CustomValue -> Either String Text forall l. Locale l => NonEmpty l -> CustomValue -> Either String Text forall v l. (Value v, Locale l) => NonEmpty l -> v -> Either String Text format NonEmpty l locales CustomValue v