module TextBuilderDev.Isomorphic where

import qualified Data.Text.Lazy as TextLazy
import qualified Data.Text.Lazy.Builder as TextLazyBuilder
import TextBuilder
import TextBuilderDev.Prelude

-- |
-- Evidence that there exists an unambiguous way to convert
-- a type to and from "TextBuilder".
--
-- The laws are:
--
-- - @'from' . 'to' = 'id'@
--
-- - @'to' . 'from' = 'id'@
--
-- This class does not provide implicit rendering,
-- such as from integer to its decimal representation.
-- There are multiple ways of representing an integer
-- as text (e.g., hexadecimal, binary).
-- The non-ambiguity is further enforced by the presence of
-- the inverse conversion.
-- In the integer case there is no way to read it
-- from a textual form without a possibility of failing
-- (e.g., when the input string cannot be parsed as an integer).
class Isomorphic a where
  -- | Project the type into "TextBuilder".
  from :: a -> TextBuilder

  -- | Embed "TextBuilder" into the type.
  to :: TextBuilder -> a

instance Isomorphic TextBuilder where
  from :: TextBuilder -> TextBuilder
from = TextBuilder -> TextBuilder
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id
  to :: TextBuilder -> TextBuilder
to = TextBuilder -> TextBuilder
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id

instance Isomorphic Text where
  from :: Text -> TextBuilder
from = Text -> TextBuilder
text
  to :: TextBuilder -> Text
to = TextBuilder -> Text
toText

instance Isomorphic TextLazy.Text where
  from :: Text -> TextBuilder
from = Text -> TextBuilder
lazyText
  to :: TextBuilder -> Text
to = Text -> Text
TextLazy.fromStrict (Text -> Text) -> (TextBuilder -> Text) -> TextBuilder -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. TextBuilder -> Text
toText

instance Isomorphic TextLazyBuilder.Builder where
  from :: Builder -> TextBuilder
from = Text -> TextBuilder
lazyText (Text -> TextBuilder)
-> (Builder -> Text) -> Builder -> TextBuilder
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Builder -> Text
TextLazyBuilder.toLazyText
  to :: TextBuilder -> Builder
to = Text -> Builder
TextLazyBuilder.fromText (Text -> Builder)
-> (TextBuilder -> Text) -> TextBuilder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. TextBuilder -> Text
toText