    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