Metadata revisions for lawful-conversions-0.1.1

Package maintainers and Hackage trustees are allowed to edit certain bits of package metadata after a release, without uploading a new tarball. Note that the tarball itself is never changed, just the metadata that is stored separately. For more information about metadata revisions, please refer to the Hackage Metadata Revisions FAQ.

No. Time User SHA256
-r5 (lawful-conversions-0.1.1-r5) 2024-12-04T06:18:42Z NikitaVolkov 176e908155df2de5c499690b16288366fa09970cc2101f7245b096a4a99c82a8
  • Changed description from

    # Summary
    
    Lawful typeclasses capturing three main patterns of bidirectional mapping. The typeclasses form a layered hierarchy with ascending strictness of laws:
    
    1. `IsSome`: Smart constructor pattern
    
    2. `IsMany`: Lossy conversion
    
    3. `Is`: Isomorphism (lossless conversion)
    
    # The conversion problem
    
    Have you ever looked for a `toString` function? How often do you
    import `Data.Text.Lazy` only to call its `Data.Text.Lazy.fromStrict`? How
    about importing `Data.ByteString.Builder` only to call its
    `Data.ByteString.Builder.toLazyByteString` and then importing
    `Data.ByteString.Lazy` only to call its `Data.ByteString.Lazy.toStrict`?
    
    Those all are instances of one pattern. They are conversions between
    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 codereader, it's a burden to the
    implementor and the maintainer.
    
    # Why another conversion library?
    
    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 behaviour 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 hierarchy, making it
    evident what any of its instances do and it provides property-tests for you
    to validate your instances.
    to
    = Summary
    
    Lawful typeclasses capturing three patterns of bidirectional mapping and forming a layered hierarchy with an ascending strictness of laws.
    
    1. `IsSome`: Smart constructor
    
    2. `IsMany`: Lossy conversion
    
    3. `Is`: Isomorphism or lossless conversion
    
    = The conversion problem
    
    Have you ever looked for a @toString@ function? How often do you
    import @Data.Text.Lazy@ only to call its 'Data.Text.Lazy.fromStrict'? How
    about importing @Data.ByteString.Builder@ only to call its
    'Data.ByteString.Builder.toLazyByteString' and then importing
    @Data.ByteString.Lazy@ only to call its 'Data.ByteString.Lazy.toStrict'?
    
    Those all are 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 codereader, it's a burden to the
    implementor and the maintainer.
    
    = Why another conversion library?
    
    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 behaviour 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 hierarchy, making it
    evident what any of its instances do and it provides property-tests for you
    to validate your instances.

-r4 (lawful-conversions-0.1.1-r4) 2024-12-04T06:17:57Z NikitaVolkov 0fc4fc2cfcc69ff336bbe0863eeddb54355859319c1eee0c8ceb5e8a6444e588
  • Changed description from

    Lawful typeclasses capturing three main patterns of bidirectional mapping. The typeclasses form a layered hierarchy with ascending strictness of laws.
    
    1. `IsSome`: Smart constructor
    
    2. `IsMany`: Lossy conversion
    
    3. `Is`: Isomorphism or lossless conversion
    
    = The conversion problem
    
    Have you ever looked for a @toString@ function? How often do you
    import @Data.Text.Lazy@ only to call its 'Data.Text.Lazy.fromStrict'? How
    about importing @Data.ByteString.Builder@ only to call its
    'Data.ByteString.Builder.toLazyByteString' and then importing
    @Data.ByteString.Lazy@ only to call its 'Data.ByteString.Lazy.toStrict'?
    
    Those all are instances of one pattern. They are conversions between
    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 codereader, it's a burden to the
    implementor and the maintainer.
    
    = Why another conversion library?
    
    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 behaviour 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 hierarchy, making it
    evident what any of its instances do and it provides property-tests for you
    to validate your instances.
    
    = Conversions
    
    The main part of the API is two functions: 'to' and 'from'. Both
    perform a conversion between two types. The main difference between them
    is in what the first type application parameter specifies. E.g.:
    
    > toString = to @String
    
    > fromText = from @Text
    
    The types should be self-evident:
    
    > > :t to @String
    > to @String :: IsSome String b => b -> String
    
    > > :t from @Text
    > from @Text :: IsMany Text b => Text -> b
    
    In other words 'to' and 'from' 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.
    
    == Examples
    
    @
    renderNameAndHeight :: 'Text' -> 'Int' -> 'Text'
    renderNameAndHeight name height =
      'from' @'Data.Text.Encoding.StrictTextBuilder' $
        "Height of " <> 'to' name <> " is " <> 'to' (show height)
    @
    
    @
    combineEncodings :: 'Data.ByteString.Short.ShortByteString' -> 'Data.Primitive.ByteArray' -> ['Word8'] -> 'Data.ByteString.Lazy.ByteString'
    combineEncodings a b c =
      'from' @'Data.ByteString.Builder.Builder' $
        'to' a <> 'to' b <> 'to' c
    @
    
    = Partial conversions
    
    This library also captures the pattern of smart constructors via the 'IsSome' class, which associates a total 'to' conversion with its partial inverse 'maybeFrom'.
    
    This captures the codec relationship between types.
    E.g.,
    
    - Every 'Int16' can be losslessly converted into 'Int32', but not every 'Int32' can be losslessly converted into 'Int16'.
    
    - Every 'Text' can be converted into 'ByteString' via UTF-8 encoding, but not every 'ByteString' forms a valid UTF-8 sequence.
    
    - Every URL can be uniquely represented as 'Text', but most 'Text's are not URLs unfortunately.
    to
    # Summary
    
    Lawful typeclasses capturing three main patterns of bidirectional mapping. The typeclasses form a layered hierarchy with ascending strictness of laws:
    
    1. `IsSome`: Smart constructor pattern
    
    2. `IsMany`: Lossy conversion
    
    3. `Is`: Isomorphism (lossless conversion)
    
    # The conversion problem
    
    Have you ever looked for a `toString` function? How often do you
    import `Data.Text.Lazy` only to call its `Data.Text.Lazy.fromStrict`? How
    about importing `Data.ByteString.Builder` only to call its
    `Data.ByteString.Builder.toLazyByteString` and then importing
    `Data.ByteString.Lazy` only to call its `Data.ByteString.Lazy.toStrict`?
    
    Those all are instances of one pattern. They are conversions between
    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 codereader, it's a burden to the
    implementor and the maintainer.
    
    # Why another conversion library?
    
    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 behaviour 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 hierarchy, making it
    evident what any of its instances do and it provides property-tests for you
    to validate your instances.

-r3 (lawful-conversions-0.1.1-r3) 2024-12-04T06:01:16Z NikitaVolkov 85762616fc1acbcf643f9da133ef2f248328fda5d0b65d1bbe9f363df572159b
  • Changed description from

    Lawful typeclasses capturing three main patterns of bidirectional mapping. The typeclasses form a layered hierarchy with ascending strictness of laws.
    
    1. `LawfulConversions.IsSome`: Smart constructor
    
    2. `LawfulConversions.IsMany`: Lossy conversion
    
    3. `LawfulConversions.Is`: Isomorphism or lossless conversion
    
    = The conversion problem
    
    Have you ever looked for a @toString@ function? How often do you
    import @Data.Text.Lazy@ only to call its 'Data.Text.Lazy.fromStrict'? How
    about importing @Data.ByteString.Builder@ only to call its
    'Data.ByteString.Builder.toLazyByteString' and then importing
    @Data.ByteString.Lazy@ only to call its 'Data.ByteString.Lazy.toStrict'?
    
    Those all are instances of one pattern. They are conversions between
    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 codereader, it's a burden to the
    implementor and the maintainer.
    
    = Why another conversion library?
    
    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 behaviour 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 hierarchy, making it
    evident what any of its instances do and it provides property-tests for you
    to validate your instances.
    
    = Conversions
    
    The main part of the API is two functions: 'LawfulConversions.to' and 'LawfulConversions.from'. Both
    perform a conversion between two types. The main difference between them
    is in what the first type application parameter specifies. E.g.:
    
    > toString = to @String
    
    > fromText = from @Text
    
    The types should be self-evident:
    
    > > :t to @String
    > to @String :: IsSome String b => b -> String
    
    > > :t from @Text
    > from @Text :: IsMany Text b => Text -> b
    
    In other words 'LawfulConversions.to' and 'LawfulConversions.from' 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.
    
    == Examples
    
    @
    renderNameAndHeight :: 'Text' -> 'Int' -> 'Text'
    renderNameAndHeight name height =
      'LawfulConversions.from' @'Data.Text.Encoding.StrictTextBuilder' $
        "Height of " <> 'LawfulConversions.to' name <> " is " <> 'LawfulConversions.to' (show height)
    @
    
    @
    combineEncodings :: 'Data.ByteString.Short.ShortByteString' -> 'Data.Primitive.ByteArray' -> ['Word8'] -> 'Data.ByteString.Lazy.ByteString'
    combineEncodings a b c =
      'LawfulConversions.from' @'Data.ByteString.Builder.Builder' $
        'LawfulConversions.to' a <> 'LawfulConversions.to' b <> 'LawfulConversions.to' c
    @
    
    = Partial conversions
    
    This library also captures the pattern of smart constructors via the 'LawfulConversions.IsSome' class, which associates a total 'LawfulConversions.to' conversion with its partial inverse 'LawfulConversions.maybeFrom'.
    
    This captures the codec relationship between types.
    E.g.,
    
    - Every 'Int16' can be losslessly converted into 'Int32', but not every 'Int32' can be losslessly converted into 'Int16'.
    
    - Every 'Text' can be converted into 'ByteString' via UTF-8 encoding, but not every 'ByteString' forms a valid UTF-8 sequence.
    
    - Every URL can be uniquely represented as 'Text', but most 'Text's are not URLs unfortunately.
    to
    Lawful typeclasses capturing three main patterns of bidirectional mapping. The typeclasses form a layered hierarchy with ascending strictness of laws.
    
    1. `IsSome`: Smart constructor
    
    2. `IsMany`: Lossy conversion
    
    3. `Is`: Isomorphism or lossless conversion
    
    = The conversion problem
    
    Have you ever looked for a @toString@ function? How often do you
    import @Data.Text.Lazy@ only to call its 'Data.Text.Lazy.fromStrict'? How
    about importing @Data.ByteString.Builder@ only to call its
    'Data.ByteString.Builder.toLazyByteString' and then importing
    @Data.ByteString.Lazy@ only to call its 'Data.ByteString.Lazy.toStrict'?
    
    Those all are instances of one pattern. They are conversions between
    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 codereader, it's a burden to the
    implementor and the maintainer.
    
    = Why another conversion library?
    
    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 behaviour 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 hierarchy, making it
    evident what any of its instances do and it provides property-tests for you
    to validate your instances.
    
    = Conversions
    
    The main part of the API is two functions: 'to' and 'from'. Both
    perform a conversion between two types. The main difference between them
    is in what the first type application parameter specifies. E.g.:
    
    > toString = to @String
    
    > fromText = from @Text
    
    The types should be self-evident:
    
    > > :t to @String
    > to @String :: IsSome String b => b -> String
    
    > > :t from @Text
    > from @Text :: IsMany Text b => Text -> b
    
    In other words 'to' and 'from' 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.
    
    == Examples
    
    @
    renderNameAndHeight :: 'Text' -> 'Int' -> 'Text'
    renderNameAndHeight name height =
      'from' @'Data.Text.Encoding.StrictTextBuilder' $
        "Height of " <> 'to' name <> " is " <> 'to' (show height)
    @
    
    @
    combineEncodings :: 'Data.ByteString.Short.ShortByteString' -> 'Data.Primitive.ByteArray' -> ['Word8'] -> 'Data.ByteString.Lazy.ByteString'
    combineEncodings a b c =
      'from' @'Data.ByteString.Builder.Builder' $
        'to' a <> 'to' b <> 'to' c
    @
    
    = Partial conversions
    
    This library also captures the pattern of smart constructors via the 'IsSome' class, which associates a total 'to' conversion with its partial inverse 'maybeFrom'.
    
    This captures the codec relationship between types.
    E.g.,
    
    - Every 'Int16' can be losslessly converted into 'Int32', but not every 'Int32' can be losslessly converted into 'Int16'.
    
    - Every 'Text' can be converted into 'ByteString' via UTF-8 encoding, but not every 'ByteString' forms a valid UTF-8 sequence.
    
    - Every URL can be uniquely represented as 'Text', but most 'Text's are not URLs unfortunately.

-r2 (lawful-conversions-0.1.1-r2) 2024-12-04T05:53:37Z NikitaVolkov 9ec257c52deb296660e3cd18bc6aaf76a8d9aaf9fc4c0bca0190b4bfded48212
  • Changed description from

    Lawful typeclasses capturing three main patterns of bidirectional mapping. The typeclasses form a layered hierarchy with ascending strictness of laws.
    
    1. `IsSome`: Smart constructor
    
    2. `IsMany`: Lossy conversion
    
    3. `Is`: Isomorphism or lossless conversion
    
    = The conversion problem
    
    Have you ever looked for a @toString@ function? How often do you
    import @Data.Text.Lazy@ only to call its 'Data.Text.Lazy.fromStrict'? How
    about importing @Data.ByteString.Builder@ only to call its
    'Data.ByteString.Builder.toLazyByteString' and then importing
    @Data.ByteString.Lazy@ only to call its 'Data.ByteString.Lazy.toStrict'?
    
    Those all are instances of one pattern. They are conversions between
    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 codereader, it's a burden to the
    implementor and the maintainer.
    
    = Why another conversion library?
    
    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 behaviour 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 hierarchy, making it
    evident what any of its instances do and it provides property-tests for you
    to validate your instances.
    
    = Conversions
    
    The main part of the API is two functions: 'to' and 'from'. Both
    perform a conversion between two types. The main difference between them
    is in what the first type application parameter specifies. E.g.:
    
    > toString = to @String
    
    > fromText = from @Text
    
    The types should be self-evident:
    
    > > :t to @String
    > to @String :: IsSome String b => b -> String
    
    > > :t from @Text
    > from @Text :: IsMany Text b => Text -> b
    
    In other words 'to' and 'from' 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.
    
    == Examples
    
    @
    renderNameAndHeight :: 'Text' -> 'Int' -> 'Text'
    renderNameAndHeight name height =
      'from' @'Data.Text.Encoding.StrictTextBuilder' $
        "Height of " <> 'to' name <> " is " <> 'to' (show height)
    @
    
    @
    combineEncodings :: 'Data.ByteString.Short.ShortByteString' -> 'Data.Primitive.ByteArray' -> ['Word8'] -> 'Data.ByteString.Lazy.ByteString'
    combineEncodings a b c =
      'from' @'Data.ByteString.Builder.Builder' $
        'to' a <> 'to' b <> 'to' c
    @
    
    = Partial conversions
    
    This library also captures the pattern of smart constructors via the 'IsSome' class, which associates a total 'to' conversion with its partial inverse 'maybeFrom'.
    
    This captures the codec relationship between types.
    E.g.,
    
    - Every 'Int16' can be losslessly converted into 'Int32', but not every 'Int32' can be losslessly converted into 'Int16'.
    
    - Every 'Text' can be converted into 'ByteString' via UTF-8 encoding, but not every 'ByteString' forms a valid UTF-8 sequence.
    
    - Every URL can be uniquely represented as 'Text', but most 'Text's are not URLs unfortunately.
    to
    Lawful typeclasses capturing three main patterns of bidirectional mapping. The typeclasses form a layered hierarchy with ascending strictness of laws.
    
    1. `LawfulConversions.IsSome`: Smart constructor
    
    2. `LawfulConversions.IsMany`: Lossy conversion
    
    3. `LawfulConversions.Is`: Isomorphism or lossless conversion
    
    = The conversion problem
    
    Have you ever looked for a @toString@ function? How often do you
    import @Data.Text.Lazy@ only to call its 'Data.Text.Lazy.fromStrict'? How
    about importing @Data.ByteString.Builder@ only to call its
    'Data.ByteString.Builder.toLazyByteString' and then importing
    @Data.ByteString.Lazy@ only to call its 'Data.ByteString.Lazy.toStrict'?
    
    Those all are instances of one pattern. They are conversions between
    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 codereader, it's a burden to the
    implementor and the maintainer.
    
    = Why another conversion library?
    
    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 behaviour 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 hierarchy, making it
    evident what any of its instances do and it provides property-tests for you
    to validate your instances.
    
    = Conversions
    
    The main part of the API is two functions: 'LawfulConversions.to' and 'LawfulConversions.from'. Both
    perform a conversion between two types. The main difference between them
    is in what the first type application parameter specifies. E.g.:
    
    > toString = to @String
    
    > fromText = from @Text
    
    The types should be self-evident:
    
    > > :t to @String
    > to @String :: IsSome String b => b -> String
    
    > > :t from @Text
    > from @Text :: IsMany Text b => Text -> b
    
    In other words 'LawfulConversions.to' and 'LawfulConversions.from' 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.
    
    == Examples
    
    @
    renderNameAndHeight :: 'Text' -> 'Int' -> 'Text'
    renderNameAndHeight name height =
      'LawfulConversions.from' @'Data.Text.Encoding.StrictTextBuilder' $
        "Height of " <> 'LawfulConversions.to' name <> " is " <> 'LawfulConversions.to' (show height)
    @
    
    @
    combineEncodings :: 'Data.ByteString.Short.ShortByteString' -> 'Data.Primitive.ByteArray' -> ['Word8'] -> 'Data.ByteString.Lazy.ByteString'
    combineEncodings a b c =
      'LawfulConversions.from' @'Data.ByteString.Builder.Builder' $
        'LawfulConversions.to' a <> 'LawfulConversions.to' b <> 'LawfulConversions.to' c
    @
    
    = Partial conversions
    
    This library also captures the pattern of smart constructors via the 'LawfulConversions.IsSome' class, which associates a total 'LawfulConversions.to' conversion with its partial inverse 'LawfulConversions.maybeFrom'.
    
    This captures the codec relationship between types.
    E.g.,
    
    - Every 'Int16' can be losslessly converted into 'Int32', but not every 'Int32' can be losslessly converted into 'Int16'.
    
    - Every 'Text' can be converted into 'ByteString' via UTF-8 encoding, but not every 'ByteString' forms a valid UTF-8 sequence.
    
    - Every URL can be uniquely represented as 'Text', but most 'Text's are not URLs unfortunately.

-r1 (lawful-conversions-0.1.1-r1) 2024-12-04T05:48:29Z NikitaVolkov 122baa7ec69d983da1feadeed66064543376395bed40a5a6ad12fba0e292ba43
  • Changed synopsis from

    Lawful typeclasses for conversion between types
    to
    Lawful typeclasses for bidirectional conversion between types

  • Changed description

    Lawful typeclasses capturing three main patterns of bidirectional mapping. The typeclasses form a layered hierarchy with ascending strictness of laws.
    
    1. `IsSome`: Smart constructor
    
    2. `IsMany`: Lossy conversion
    
    3. `Is`: Isomorphism or lossless conversion
    
    = The conversion problem
    
    Have you ever looked for a @toString@ function? How often do you
    import @Data.Text.Lazy@ only to call its 'Data.Text.Lazy.fromStrict'? How
    about importing @Data.ByteString.Builder@ only to call its
    'Data.ByteString.Builder.toLazyByteString' and then importing
    @Data.ByteString.Lazy@ only to call its 'Data.ByteString.Lazy.toStrict'?
    
    Those all are instances of one pattern. They are conversions between
    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 codereader, it's a burden to the
    implementor and the maintainer.
    
    = Why another conversion library?
    
    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 behaviour 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 hierarchy, making it
    evident what any of its instances do and it provides property-tests for you
    to validate your instances.
    
    = Conversions
    
    The main part of the API is two functions: 'to' and 'from'. Both
    perform a conversion between two types. The main difference between them
    is in what the first type application parameter specifies. E.g.:
    
    > toString = to @String
    
    > fromText = from @Text
    
    The types should be self-evident:
    
    > > :t to @String
    > to @String :: IsSome String b => b -> String
    
    > > :t from @Text
    > from @Text :: IsMany Text b => Text -> b
    
    In other words 'to' and 'from' 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.
    
    == Examples
    
    @
    renderNameAndHeight :: 'Text' -> 'Int' -> 'Text'
    renderNameAndHeight name height =
      'from' @'Data.Text.Encoding.StrictTextBuilder' $
        "Height of " <> 'to' name <> " is " <> 'to' (show height)
    @
    
    @
    combineEncodings :: 'Data.ByteString.Short.ShortByteString' -> 'Data.Primitive.ByteArray' -> ['Word8'] -> 'Data.ByteString.Lazy.ByteString'
    combineEncodings a b c =
      'from' @'Data.ByteString.Builder.Builder' $
        'to' a <> 'to' b <> 'to' c
    @
    
    = Partial conversions
    
    This library also captures the pattern of smart constructors via the 'IsSome' class, which associates a total 'to' conversion with its partial inverse 'maybeFrom'.
    
    This captures the codec relationship between types.
    E.g.,
    
    - Every 'Int16' can be losslessly converted into 'Int32', but not every 'Int32' can be losslessly converted into 'Int16'.
    
    - Every 'Text' can be converted into 'ByteString' via UTF-8 encoding, but not every 'ByteString' forms a valid UTF-8 sequence.
    
    - Every URL can be uniquely represented as 'Text', but most 'Text's are not URLs unfortunately.

-r0 (lawful-conversions-0.1.1-r0) 2024-12-03T02:48:06Z NikitaVolkov ac36513a8b83e2ed8b8483426abf5b02c8b2e0e454d3502abe2b6bf62f65ad41