HORIZON HASKELLDocslts/ghc-9.14.x45dd5372026-10-11Search names, modules, packages, or :: a typeCtrl K

GHC 9.14.1 · lts/ghc-9.14.x · 45dd537 · 2026-10-11

Moduleisomorphism-class-0.3.1.4Haskell2010

IsomorphismClass

UX

Essentially the whole API is just two functions: to and from. Both perform a conversion between two types. The only difference between them is in what the first type application parameter specifies. E.g.:

toText = to @Text
fromBuilder = from @Builder

The types are self-evident:

> :t to @Text
to @Text :: IsomorphicTo Text b => b -> Text
> :t from @Builder
from @Builder :: IsomorphicTo Builder b => Builder -> 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

combineEncodings :: ShortByteString -> Data.Primitive.ByteArray -> ByteString -> [Word8]
combineEncodings a b c =
  from @Builder $
    to a <> to b <> to c

Which is equivalent to:

combineEncodings :: ShortByteString -> Data.Primitive.ByteArray -> ByteString -> [Word8]
combineEncodings a b c =
  LazyByteString.unpack $
    Builder.toLazyByteString $
      mconcat
        [ Builder.shortByteString a,
          Builder.shortByteString
            ( let ByteArray.ByteArray array = b
               in ShortByteString.SBS array
            ),
          Builder.lazyByteString c
        ]
  • 1 class
  • 3 values

Typeclasses

2 declarations
classclass IsomorphicTo b a => IsomorphicTo a b where
#

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 IsomorphicTo a b as "B is isomorphic to A".

Laws

B is isomorphic to A if and only if there exists a conversion from B to A (to) and a conversion from A to B (from) such that:

  • from . to = id - For all values of B converting from B to A and then converting from A to B produces a value that is identical to the original.

  • to . from = id - For all values of A converting from A to B and then converting from B to A produces a value that is identical to the original.

Testing

For testing whether your instances conform to these laws use isomorphicToProperties.

Instance Definition

For each pair of isomorphic types (A and B) the compiler will require you to define two instances, namely: IsomorphicTo A B and IsomorphicTo B A.

Methods

  • to :: b -> a

    Convert a value into an isomophic type.

Instances69IsomorphicTo, …
valuefrom :: IsomorphicTo a b => a -> b
#

to in reverse direction.

Particularly useful in combination with the TypeApplications extension, where it allows to specify the input type, e.g.:

fromText :: IsomorphicTo Text b => Text -> b
fromText = from @Text

The first type application of the to function on the other hand specifies the output data type.

Optics

1 declaration

Testing

1 declaration