-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Isomorphism typeclass as a lawful solution to the conversion problem
--   
--   <h1>Conversion problem</h1>
--   
--   How often do you import <tt>Data.Text.Lazy</tt> only to call
--   <tt>fromStrict</tt> or <tt>toStrict</tt>? How about importing
--   <tt>Data.ByteString.Builder</tt> only to call its
--   <tt>toLazyByteString</tt> and then importing
--   <tt>Data.ByteString.Lazy</tt> only to call its <tt>toStrict</tt>? How
--   often do you convert from <tt>DiffTime</tt> to
--   <tt>NominalDiffTime</tt> or back?
--   
--   These are all instances of one pattern. They are conversions between
--   different representations of the same information. Codebases that
--   don't attempt to abstract over this pattern tend to be sprawling with
--   this type of boilerplate. It's noise to the code reader, it's a burden
--   to implementors and maintainers.
--   
--   <h1>Why another conversion library?</h1>
--   
--   Many libraries exist that approach the conversion problem. However,
--   most of them provide lawless typeclasses, leaving it up to the author
--   of the instance to define what makes a proper conversion. This results
--   in inconsistencies across instances, their behavior not being evident
--   to the user and no way to check whether an instance is correct.
--   
--   This library tackles this problem with a lawful typeclass, making it
--   evident what any of its instances do, and it provides a property-test
--   for you to validate your instances.
--   
--   <h1>The insight</h1>
--   
--   The key insight of this library is that if you add a requirement for
--   the conversion to be lossless and to have a mirror conversion in the
--   opposite direction, there usually appears to be only one way of
--   defining it. That makes it very clear what the conversion does to the
--   user and how to define it for the author of the conversion. It also
--   gives clear criteria for validating whether the instances are correct,
--   which can be encoded in property-tests.
--   
--   That insight itself stems from an observation that almost all of the
--   practical conversions in Haskell share a property: you can restore the
--   original data from its converted form. E.g., you can get a text from a
--   text-builder and you can create a text-builder from a text, you can
--   convert a bytestring into a list of bytes and vice-versa, bytestring
--   to/from bytearray, strict bytestring to/from lazy, list to/from
--   sequence, sequence to/from vector, set of ints to/from int-set. In
--   other words, it's always a two-way street with them and there are many
--   instances of this pattern.
--   
--   A few other accidental findings like encoding this property with
--   recursive typeclass constraints and fine-tuning for the use of the
--   <tt>TypeApplications</tt> extension resulted in a terse and clear API.
--   
--   <h1>Other work and acknowledgements</h1>
--   
--   <ul>
--   <li><a>lawful-conversions</a> - sibling of this library expanding upon
--   the same insights to also cover the patterns of smart construction and
--   canonicalization. It's more involved and has different tradeoffs. Both
--   libraries are maintained, letting their designs compete.</li>
--   </ul>
--   
--   Some ideas and concepts are also shared with the following libraries:
--   
--   <ul>
--   <li><a>control-iso</a></li>
--   <li><a>type-iso</a></li>
--   <li><a>injections</a></li>
--   </ul>
@package isomorphism-class
@version 0.3.1.2


-- | <h1>UX</h1>
--   
--   Essentially the whole API is just two functions: <a>to</a> and
--   <a>from</a>. Both perform a conversion between two types. The only
--   difference between them is in what the first type application
--   parameter specifies. E.g.:
--   
--   <pre>
--   toText = to @Text
--   </pre>
--   
--   <pre>
--   fromBuilder = from @Builder
--   </pre>
--   
--   The types are self-evident:
--   
--   <pre>
--   &gt; :t to @Text
--   to @Text :: IsomorphicTo Text b =&gt; b -&gt; Text
--   </pre>
--   
--   <pre>
--   &gt; :t from @Builder
--   from @Builder :: IsomorphicTo Builder b =&gt; Builder -&gt; b
--   </pre>
--   
--   In other words <a>to</a> and <a>from</a> let you explicitly specify
--   either the source or the target type of a conversion when you need to
--   help the type inferencer or the reader.
--   
--   <h1>Examples</h1>
--   
--   <pre>
--   combineEncodings :: <a>ShortByteString</a> -&gt; <a>ByteArray</a> -&gt; <a>ByteString</a> -&gt; [Word8]
--   combineEncodings a b c =
--     <a>from</a> @<a>Builder</a> $
--       <a>to</a> a &lt;&gt; <a>to</a> b &lt;&gt; <a>to</a> c
--   </pre>
--   
--   Which is equivalent to:
--   
--   <pre>
--   combineEncodings :: <a>ShortByteString</a> -&gt; <a>ByteArray</a> -&gt; <a>ByteString</a> -&gt; [Word8]
--   combineEncodings a b c =
--     LazyByteString.<a>unpack</a> $
--       Builder.<a>toLazyByteString</a> $
--         mconcat
--           [ Builder.<a>shortByteString</a> a,
--             Builder.<a>shortByteString</a>
--               ( let ByteArray.<a>ByteArray</a> array = b
--                  in ShortByteString.<a>SBS</a> array
--               ),
--             Builder.<a>lazyByteString</a> c
--           ]
--   </pre>
module IsomorphismClass

-- | Bidirectional conversion between two types with no loss of
--   information.
--   
--   The bidirectionality is encoded via a recursive dependency with
--   arguments flipped.
--   
--   You can read the signature <tt>IsomorphicTo a b</tt> as "<i>B</i> is
--   isomorphic to <i>A</i>".
--   
--   <h3>Laws</h3>
--   
--   <i>B</i> is isomorphic to <i>A</i> if and only if there exists a
--   conversion from <i>B</i> to <i>A</i> (<a>to</a>) and a conversion from
--   <i>A</i> to <i>B</i> (<a>from</a>) such that:
--   
--   <ul>
--   <li><tt><a>from</a> . <a>to</a> = <a>id</a></tt> - For all values of
--   <i>B</i> converting from <i>B</i> to <i>A</i> and then converting from
--   <i>A</i> to <i>B</i> produces a value that is identical to the
--   original.</li>
--   <li><tt><a>to</a> . <a>from</a> = <a>id</a></tt> - For all values of
--   <i>A</i> converting from <i>A</i> to <i>B</i> and then converting from
--   <i>B</i> to <i>A</i> produces a value that is identical to the
--   original.</li>
--   </ul>
--   
--   <h3>Testing</h3>
--   
--   For testing whether your instances conform to these laws use
--   <a>isomorphicToProperties</a>.
--   
--   <h3>Instance Definition</h3>
--   
--   For each pair of isomorphic types (<i>A</i> and <i>B</i>) the compiler
--   will require you to define two instances, namely: <tt>IsomorphicTo A
--   B</tt> and <tt>IsomorphicTo B A</tt>.
class IsomorphicTo b a => IsomorphicTo a b

-- | Convert a value into an isomophic type.
to :: IsomorphicTo a b => b -> a

-- | <a>to</a> in reverse direction.
--   
--   Particularly useful in combination with the <tt>TypeApplications</tt>
--   extension, where it allows to specify the input type, e.g.:
--   
--   <pre>
--   fromText :: IsomorphicTo Text b =&gt; Text -&gt; b
--   fromText = from @Text
--   </pre>
--   
--   The first type application of the <a>to</a> function on the other hand
--   specifies the output data type.
from :: IsomorphicTo a b => a -> b

-- | Van-Laarhoven-style Isomorphism, compatible with the "lens" library.
isomorphicToIso :: (IsomorphicTo a b, Profunctor p, Functor f) => p b (f b) -> p a (f a)

-- | Properties testing whether an instance satisfies the laws of
--   <a>IsomorphicTo</a>.
--   
--   The instance is identified via the proxy types that you provide.
--   
--   E.g., here's how you can integrate it into an Hspec test-suite:
--   
--   <pre>
--   spec = do
--     describe "IsomorphicTo laws" do
--       traverse_
--         (uncurry prop)
--         (isomorphicToProperties @Int32 @Word32 Proxy Proxy)
--   </pre>
isomorphicToProperties :: (IsomorphicTo a b, Eq a, Eq b, Arbitrary a, Show a, Arbitrary b, Show b) => Proxy a -> Proxy b -> [(String, Property)]
