cabal-version: 3.0
name: isomorphism-class
version: 0.3.1.2
synopsis: Isomorphism typeclass as a lawful solution to the conversion problem
description:
= Conversion problem
How often do you import @Data.Text.Lazy@ only to call @fromStrict@ or @toStrict@?
How about importing @Data.ByteString.Builder@ only to call its
@toLazyByteString@ and then importing
@Data.ByteString.Lazy@ only to call its @toStrict@?
How often do you convert from @DiffTime@ to @NominalDiffTime@ 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.
= 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 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.
= The insight
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 @TypeApplications@ extension resulted in a terse and clear API.
= Other work and acknowledgements
- [lawful-conversions](https://hackage.haskell.org/package/lawful-conversions) - 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.
Some ideas and concepts are also shared with the following libraries:
- [control-iso](https://hackage.haskell.org/package/control-iso)
- [type-iso](https://hackage.haskell.org/package/type-iso)
- [injections](https://hackage.haskell.org/package/injections)
category: Conversion
homepage: https://github.com/nikita-volkov/isomorphism-class
bug-reports: https://github.com/nikita-volkov/isomorphism-class/issues
author: Nikita Volkov <nikita.y.volkov@mail.ru>
maintainer: Nikita Volkov <nikita.y.volkov@mail.ru>
copyright: (c) 2022 Nikita Volkov
license: MIT
license-file: LICENSE
extra-doc-files:
CHANGELOG.md
source-repository head
type: git
location: https://github.com/nikita-volkov/isomorphism-class
common language-settings
default-language: Haskell2010
default-extensions:
BlockArguments
DefaultSignatures
FlexibleContexts
FlexibleInstances
MagicHash
MultiParamTypeClasses
NoImplicitPrelude
ScopedTypeVariables
TypeApplications
UndecidableSuperClasses
library
import: language-settings
hs-source-dirs: library
exposed-modules: IsomorphismClass
other-modules:
IsomorphismClass.Classes
IsomorphismClass.Classes.IsomorphicTo
IsomorphismClass.Optics
IsomorphismClass.Prelude
IsomorphismClass.Properties
IsomorphismClass.Relations
IsomorphismClass.Relations.BoxedVectorAndList
IsomorphismClass.Relations.BoxedVectorAndSeq
IsomorphismClass.Relations.ByteArrayAndByteString
IsomorphismClass.Relations.ByteArrayAndLazyByteString
IsomorphismClass.Relations.ByteArrayAndLazyByteStringBuilder
IsomorphismClass.Relations.ByteArrayAndShortByteString
IsomorphismClass.Relations.ByteArrayAndTextArray
IsomorphismClass.Relations.ByteArrayAndWord8List
IsomorphismClass.Relations.ByteStringAndLazyByteString
IsomorphismClass.Relations.ByteStringAndLazyByteStringBuilder
IsomorphismClass.Relations.ByteStringAndShortByteString
IsomorphismClass.Relations.ByteStringAndTextArray
IsomorphismClass.Relations.ByteStringAndWord8List
IsomorphismClass.Relations.DiffTimeAndNominalDiffTime
IsomorphismClass.Relations.DiffTimeAndPico
IsomorphismClass.Relations.Int16AndWord16
IsomorphismClass.Relations.Int32AndWord32
IsomorphismClass.Relations.Int64AndWord64
IsomorphismClass.Relations.Int8AndWord8
IsomorphismClass.Relations.IntAndWord
IsomorphismClass.Relations.IntMapAndMapOfInt
IsomorphismClass.Relations.IntSetAndSetOfInt
IsomorphismClass.Relations.LazyByteStringAndLazyByteStringBuilder
IsomorphismClass.Relations.LazyByteStringAndShortByteString
IsomorphismClass.Relations.LazyByteStringAndTextArray
IsomorphismClass.Relations.LazyByteStringAndWord8List
IsomorphismClass.Relations.LazyByteStringBuilderAndShortByteString
IsomorphismClass.Relations.LazyByteStringBuilderAndTextArray
IsomorphismClass.Relations.LazyByteStringBuilderAndWord8List
IsomorphismClass.Relations.LazyTextAndLazyTextBuilder
IsomorphismClass.Relations.LazyTextAndStrictTextBuilder
IsomorphismClass.Relations.LazyTextAndText
IsomorphismClass.Relations.LazyTextBuilderAndStrictTextBuilder
IsomorphismClass.Relations.LazyTextBuilderAndText
IsomorphismClass.Relations.ListAndSeq
IsomorphismClass.Relations.NominalDiffTimeAndPico
IsomorphismClass.Relations.ShortByteStringAndTextArray
IsomorphismClass.Relations.ShortByteStringAndWord8List
IsomorphismClass.Relations.StrictTextBuilderAndText
IsomorphismClass.Relations.TextArrayAndWord8List
IsomorphismClass.TextCompat.Array
build-depends:
QuickCheck >=2.13 && <3,
base >=4.12 && <5,
bytestring >=0.10 && <0.13,
containers >=0.6 && <0.8,
hashable >=1 && <2,
primitive >=0.7 && <0.10,
profunctors >=5 && <6,
text >=1.2 && <2.2,
time >=1.9 && <2,
unordered-containers >=0.2 && <0.3,
vector >=0.12 && <0.14,
test-suite test
import: language-settings
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: Main.hs
other-modules: Test.ExtraInstances
build-depends:
QuickCheck >=2.13 && <3,
bytestring >=0.11.1.0 && <0.13,
isomorphism-class,
primitive >=0.7 && <0.10,
quickcheck-instances >=0.3.32 && <0.4,
rebase >=1.15 && <2,
tasty >=1.2.3 && <2,
tasty-quickcheck >=0.10.1 && <0.12,
text >=1.2 && <3,