lawful-conversions-0.4.0: Lawful typeclasses for bidirectional conversion between types
Safe HaskellNone
LanguageHaskell2010

LawfulConversions

Description

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 :: IsSome a Text => Text -> a

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 -> ByteArray -> [Word8] -> ByteString
combineEncodings a b c =
  from @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 Texts are not URLs unfortunately.
  • UTCTime, JSON, Email, etc.

Examples

Here's an example of implementing the Smart Constructor pattern.

module Percent (Percent) where

import LawfulConversions

newtype Percent = Percent Double

instance IsSome Double Percent where
  to (Percent double) = double
  maybeFrom double =
    if double < 0 || double > 1
      then Nothing
      else Just (Percent double)

You can also expand upon that and provide a default handling of invalid values effectively providing a lossy canonicalizing conversion (Surjection):

instance IsMany Double Percent where
  onfrom double =
    if double < 0
      then Percent 0
      else if double > 1
        then Percent 1
        else Percent double

However declaring an instance of Is would be incorrect, because this conversion is partial. Namely, while every Percent value can be losslessly transformed into Double, not every Double can be losslessly transformed into Percent.

Synopsis

Typeclasses

class IsSome a b where Source #

Evidence that all values of type b form a subset of all values of type a.

From Wikipedia:

In mathematics, a set A is a subset of a set B if all elements of A are also elements of B; B is then a superset of A. It is possible for A and B to be equal; if they are unequal, then A is a proper subset of B. The relationship of one set being a subset of another is called inclusion (or sometimes containment). A is a subset of B may also be expressed as B includes (or contains) A or A is included (or contained) in B. A k-subset is a subset with k elements.

Laws

to is injective

For every two values of type b that are not equal converting with to produces values that are not equal as well:

\(b1, b2) -> b1 == b2 || to @a b1 /= to @a b2

maybeFrom is a partial inverse of to

For all values of b converting to a and then attempting to convert back to b always succeeds and produces a value that is equal to the original:

\b -> maybeFrom (to @a b) == Just b

maybeFrom characterizes the image of to

maybeFrom succeeds exactly on values that are in the image of to:

\a b -> maybeFrom a == Just b ==> to b == a

Mathematical foundation

These laws establish that type b forms a subset of type a in the mathematical sense. The to function provides the canonical injection, while maybeFrom recognizes which values of a correspond to values from the subset b.

Testing

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

Minimal complete definition

to

Methods

to :: b -> a Source #

Convert a value of a subset type to a superset type.

maybeFrom :: a -> Maybe b Source #

default maybeFrom :: IsSome b a => a -> Maybe b Source #

Requires the presence of IsSome in reverse direction.

Instances

Instances details
IsSome ByteArray Builder Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndLazyByteStringBuilder

IsSome ByteArray ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndByteString

IsSome ByteArray ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndLazyByteString

IsSome ByteArray ShortByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndShortByteString

IsSome Int16 Word16 Source # 
Instance details

Defined in LawfulConversions.Relations.Int16AndWord16

IsSome Int32 Word32 Source # 
Instance details

Defined in LawfulConversions.Relations.Int32AndWord32

IsSome Int64 Word64 Source # 
Instance details

Defined in LawfulConversions.Relations.Int64AndWord64

IsSome Int8 Word8 Source # 
Instance details

Defined in LawfulConversions.Relations.Int8AndWord8

IsSome Word16 Int16 Source # 
Instance details

Defined in LawfulConversions.Relations.Int16AndWord16

IsSome Word32 Int32 Source # 
Instance details

Defined in LawfulConversions.Relations.Int32AndWord32

IsSome Word64 Int64 Source # 
Instance details

Defined in LawfulConversions.Relations.Int64AndWord64

IsSome Word8 Int8 Source # 
Instance details

Defined in LawfulConversions.Relations.Int8AndWord8

IsSome Builder ByteArray Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndLazyByteStringBuilder

IsSome Builder ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndLazyByteStringBuilder

IsSome Builder ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndLazyByteStringBuilder

IsSome Builder ShortByteString Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringBuilderAndShortByteString

IsSome ByteString ByteArray Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndByteString

IsSome ByteString Builder Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndLazyByteStringBuilder

IsSome ByteString ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndLazyByteString

IsSome ByteString ShortByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndShortByteString

IsSome ByteString ByteArray Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndLazyByteString

IsSome ByteString Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndLazyByteStringBuilder

IsSome ByteString ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndLazyByteString

IsSome ByteString ShortByteString Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndShortByteString

IsSome ShortByteString ByteArray Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndShortByteString

IsSome ShortByteString Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringBuilderAndShortByteString

IsSome ShortByteString ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndShortByteString

IsSome ShortByteString ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndShortByteString

IsSome Text Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextBuilderAndText

IsSome Text Text Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndText

IsSome Text StrictBuilder Source # 
Instance details

Defined in LawfulConversions.Relations.StrictTextBuilderAndText

IsSome Builder Text Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextBuilderAndText

IsSome Builder Text Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndLazyTextBuilder

IsSome Builder StrictBuilder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextBuilderAndStrictTextBuilder

IsSome Text Text Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndText

IsSome Text Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndLazyTextBuilder

IsSome Text StrictBuilder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndStrictTextBuilder

IsSome StrictBuilder Text Source # 
Instance details

Defined in LawfulConversions.Relations.StrictTextBuilderAndText

IsSome StrictBuilder Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextBuilderAndStrictTextBuilder

IsSome StrictBuilder Text Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndStrictTextBuilder

IsSome String Text Source # 
Instance details

Defined in LawfulConversions.Relations.StringAndText

IsSome String Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextBuilderAndString

IsSome String Text Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndString

IsSome String StrictBuilder Source # 
Instance details

Defined in LawfulConversions.Relations.StrictTextBuilderAndString

IsSome Int Word Source # 
Instance details

Defined in LawfulConversions.Relations.IntAndWord

IsSome Word Int Source # 
Instance details

Defined in LawfulConversions.Relations.IntAndWord

IsSome a Void Source #

The empty set has no elements, and therefore is vacuously a subset of any set.

Instance details

Defined in LawfulConversions.Relations.Void

Methods

to :: Void -> a Source #

maybeFrom :: a -> Maybe Void Source #

IsSome a a Source #

Any type is isomorphic to itself.

Instance details

Defined in LawfulConversions.Relations.Any

Methods

to :: a -> a Source #

maybeFrom :: a -> Maybe a Source #

IsSome ByteArray [Word8] Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndWord8List

IsSome Builder [Word8] Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringBuilderAndWord8List

IsSome ByteString [Word8] Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndWord8List

IsSome ByteString [Word8] Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndWord8List

IsSome ShortByteString [Word8] Source # 
Instance details

Defined in LawfulConversions.Relations.ShortByteStringAndWord8List

IsSome IntSet (Set Int) Source # 
Instance details

Defined in LawfulConversions.Relations.IntSetAndSetOfInt

IsSome a b => IsSome a (ViaIsSome a b) Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

Methods

to :: ViaIsSome a b -> a Source #

maybeFrom :: a -> Maybe (ViaIsSome a b) Source #

IsSome b (ViaIsSome a b) Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

Methods

to :: ViaIsSome a b -> b Source #

maybeFrom :: b -> Maybe (ViaIsSome a b) Source #

IsSome (Set Int) IntSet Source # 
Instance details

Defined in LawfulConversions.Relations.IntSetAndSetOfInt

IsSome [Word8] ByteArray Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndWord8List

IsSome [Word8] Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringBuilderAndWord8List

IsSome [Word8] ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndWord8List

IsSome [Word8] ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndWord8List

IsSome [Word8] ShortByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ShortByteStringAndWord8List

IsSome (Seq a) (Vector a) Source # 
Instance details

Defined in LawfulConversions.Relations.BoxedVectorAndSeq

Methods

to :: Vector a -> Seq a Source #

maybeFrom :: Seq a -> Maybe (Vector a) Source #

IsSome (Seq a) [a] Source # 
Instance details

Defined in LawfulConversions.Relations.ListAndSeq

Methods

to :: [a] -> Seq a Source #

maybeFrom :: Seq a -> Maybe [a] Source #

IsSome (Vector a) (Seq a) Source # 
Instance details

Defined in LawfulConversions.Relations.BoxedVectorAndSeq

Methods

to :: Seq a -> Vector a Source #

maybeFrom :: Vector a -> Maybe (Seq a) Source #

IsSome (Vector a) [a] Source # 
Instance details

Defined in LawfulConversions.Relations.BoxedVectorAndList

Methods

to :: [a] -> Vector a Source #

maybeFrom :: Vector a -> Maybe [a] Source #

IsSome [a] (Seq a) Source # 
Instance details

Defined in LawfulConversions.Relations.ListAndSeq

Methods

to :: Seq a -> [a] Source #

maybeFrom :: [a] -> Maybe (Seq a) Source #

IsSome [a] (Vector a) Source # 
Instance details

Defined in LawfulConversions.Relations.BoxedVectorAndList

Methods

to :: Vector a -> [a] Source #

maybeFrom :: [a] -> Maybe (Vector a) Source #

IsSome (IntMap v) (Map Int v) Source # 
Instance details

Defined in LawfulConversions.Relations.IntMapAndMapOfInt

Methods

to :: Map Int v -> IntMap v Source #

maybeFrom :: IntMap v -> Maybe (Map Int v) Source #

IsSome (ViaIsSome a b) b Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

Methods

to :: b -> ViaIsSome a b Source #

maybeFrom :: ViaIsSome a b -> Maybe b Source #

IsSome (Map Int v) (IntMap v) Source # 
Instance details

Defined in LawfulConversions.Relations.IntMapAndMapOfInt

Methods

to :: IntMap v -> Map Int v Source #

maybeFrom :: Map Int v -> Maybe (IntMap v) Source #

class IsSome a b => IsMany a b where Source #

Lossy or canonicalizing conversion. Captures mappings from multiple alternative inputs into one output.

E.g.,

  • ByteString can be decoded into Text with UTF-8 leniently, replacing the invalid chars with a default char.
  • String has a wider range of supported chars than Text, so some chars get replaced too.

Laws

onfrom is an inverse of to

\b -> b == onfrom (to @a b)

onfrom is surjective

Every value of type b can be obtained by applying onfrom to some value of type a:

\b -> exists a. onfrom @a @b a == b

Note: This property cannot be directly tested with QuickCheck as it requires existential quantification.

Law hierarchy

IsMany extends IsSome, so all laws from IsSome also apply here. The combination ensures that onfrom provides a canonical (possibly lossy) conversion from a to b, while to provides the lossless injection from b to a.

Testing

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

Minimal complete definition

Nothing

Methods

onfrom :: a -> b Source #

Possibly lossy inverse of to. Surjection from a to b.

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

fromString :: IsMany String b => String -> b
fromString = onfrom @String

If you want to specify the output type instead, use onto.

default onfrom :: IsSome b a => a -> b Source #

Requires the presence of IsSome in reverse direction.

Instances

Instances details
IsMany ByteArray Builder Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndLazyByteStringBuilder

IsMany ByteArray ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndByteString

IsMany ByteArray ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndLazyByteString

IsMany ByteArray ShortByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndShortByteString

IsMany Int16 Word16 Source # 
Instance details

Defined in LawfulConversions.Relations.Int16AndWord16

Methods

onfrom :: Int16 -> Word16 Source #

IsMany Int32 Word32 Source # 
Instance details

Defined in LawfulConversions.Relations.Int32AndWord32

Methods

onfrom :: Int32 -> Word32 Source #

IsMany Int64 Word64 Source # 
Instance details

Defined in LawfulConversions.Relations.Int64AndWord64

Methods

onfrom :: Int64 -> Word64 Source #

IsMany Int8 Word8 Source # 
Instance details

Defined in LawfulConversions.Relations.Int8AndWord8

Methods

onfrom :: Int8 -> Word8 Source #

IsMany Word16 Int16 Source # 
Instance details

Defined in LawfulConversions.Relations.Int16AndWord16

Methods

onfrom :: Word16 -> Int16 Source #

IsMany Word32 Int32 Source # 
Instance details

Defined in LawfulConversions.Relations.Int32AndWord32

Methods

onfrom :: Word32 -> Int32 Source #

IsMany Word64 Int64 Source # 
Instance details

Defined in LawfulConversions.Relations.Int64AndWord64

Methods

onfrom :: Word64 -> Int64 Source #

IsMany Word8 Int8 Source # 
Instance details

Defined in LawfulConversions.Relations.Int8AndWord8

Methods

onfrom :: Word8 -> Int8 Source #

IsMany Builder ByteArray Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndLazyByteStringBuilder

IsMany Builder ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndLazyByteStringBuilder

IsMany Builder ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndLazyByteStringBuilder

IsMany Builder ShortByteString Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringBuilderAndShortByteString

IsMany ByteString ByteArray Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndByteString

IsMany ByteString Builder Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndLazyByteStringBuilder

IsMany ByteString ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndLazyByteString

IsMany ByteString ShortByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndShortByteString

IsMany ByteString ByteArray Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndLazyByteString

IsMany ByteString Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndLazyByteStringBuilder

IsMany ByteString ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndLazyByteString

IsMany ByteString ShortByteString Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndShortByteString

IsMany ShortByteString ByteArray Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndShortByteString

IsMany ShortByteString Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringBuilderAndShortByteString

IsMany ShortByteString ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndShortByteString

IsMany ShortByteString ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndShortByteString

IsMany Text Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextBuilderAndText

Methods

onfrom :: Text -> Builder Source #

IsMany Text Text Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndText

Methods

onfrom :: Text -> Text Source #

IsMany Text StrictBuilder Source # 
Instance details

Defined in LawfulConversions.Relations.StrictTextBuilderAndText

IsMany Builder Text Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextBuilderAndText

Methods

onfrom :: Builder -> Text Source #

IsMany Builder Text Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndLazyTextBuilder

Methods

onfrom :: Builder -> Text Source #

IsMany Builder StrictBuilder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextBuilderAndStrictTextBuilder

IsMany Text Text Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndText

Methods

onfrom :: Text -> Text Source #

IsMany Text Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndLazyTextBuilder

Methods

onfrom :: Text -> Builder Source #

IsMany Text StrictBuilder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndStrictTextBuilder

IsMany StrictBuilder Text Source # 
Instance details

Defined in LawfulConversions.Relations.StrictTextBuilderAndText

IsMany StrictBuilder Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextBuilderAndStrictTextBuilder

IsMany StrictBuilder Text Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndStrictTextBuilder

IsMany String Text Source # 
Instance details

Defined in LawfulConversions.Relations.StringAndText

Methods

onfrom :: String -> Text Source #

IsMany String Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextBuilderAndString

IsMany String Text Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndString

Methods

onfrom :: String -> Text Source #

IsMany String StrictBuilder Source # 
Instance details

Defined in LawfulConversions.Relations.StrictTextBuilderAndString

IsMany Int Word Source # 
Instance details

Defined in LawfulConversions.Relations.IntAndWord

Methods

onfrom :: Int -> Word Source #

IsMany Word Int Source # 
Instance details

Defined in LawfulConversions.Relations.IntAndWord

Methods

onfrom :: Word -> Int Source #

IsMany a a Source #

Any type is isomorphic to itself.

Instance details

Defined in LawfulConversions.Relations.Any

Methods

onfrom :: a -> a Source #

IsMany ByteArray [Word8] Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndWord8List

Methods

onfrom :: ByteArray -> [Word8] Source #

IsMany Builder [Word8] Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringBuilderAndWord8List

Methods

onfrom :: Builder -> [Word8] Source #

IsMany ByteString [Word8] Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndWord8List

Methods

onfrom :: ByteString -> [Word8] Source #

IsMany ByteString [Word8] Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndWord8List

Methods

onfrom :: ByteString -> [Word8] Source #

IsMany ShortByteString [Word8] Source # 
Instance details

Defined in LawfulConversions.Relations.ShortByteStringAndWord8List

IsMany IntSet (Set Int) Source # 
Instance details

Defined in LawfulConversions.Relations.IntSetAndSetOfInt

Methods

onfrom :: IntSet -> Set Int Source #

IsMany b (ViaIsSome a b) Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

Methods

onfrom :: b -> ViaIsSome a b Source #

IsMany (Set Int) IntSet Source # 
Instance details

Defined in LawfulConversions.Relations.IntSetAndSetOfInt

Methods

onfrom :: Set Int -> IntSet Source #

IsMany [Word8] ByteArray Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndWord8List

Methods

onfrom :: [Word8] -> ByteArray Source #

IsMany [Word8] Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringBuilderAndWord8List

Methods

onfrom :: [Word8] -> Builder Source #

IsMany [Word8] ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndWord8List

Methods

onfrom :: [Word8] -> ByteString Source #

IsMany [Word8] ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndWord8List

Methods

onfrom :: [Word8] -> ByteString Source #

IsMany [Word8] ShortByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ShortByteStringAndWord8List

IsMany (Seq a) (Vector a) Source # 
Instance details

Defined in LawfulConversions.Relations.BoxedVectorAndSeq

Methods

onfrom :: Seq a -> Vector a Source #

IsMany (Seq a) [a] Source # 
Instance details

Defined in LawfulConversions.Relations.ListAndSeq

Methods

onfrom :: Seq a -> [a] Source #

IsMany (Vector a) (Seq a) Source # 
Instance details

Defined in LawfulConversions.Relations.BoxedVectorAndSeq

Methods

onfrom :: Vector a -> Seq a Source #

IsMany (Vector a) [a] Source # 
Instance details

Defined in LawfulConversions.Relations.BoxedVectorAndList

Methods

onfrom :: Vector a -> [a] Source #

IsMany [a] (Seq a) Source # 
Instance details

Defined in LawfulConversions.Relations.ListAndSeq

Methods

onfrom :: [a] -> Seq a Source #

IsMany [a] (Vector a) Source # 
Instance details

Defined in LawfulConversions.Relations.BoxedVectorAndList

Methods

onfrom :: [a] -> Vector a Source #

IsMany (IntMap v) (Map Int v) Source # 
Instance details

Defined in LawfulConversions.Relations.IntMapAndMapOfInt

Methods

onfrom :: IntMap v -> Map Int v Source #

IsMany (ViaIsSome a b) b Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

Methods

onfrom :: ViaIsSome a b -> b Source #

IsMany (Map Int v) (IntMap v) Source # 
Instance details

Defined in LawfulConversions.Relations.IntMapAndMapOfInt

Methods

onfrom :: Map Int v -> IntMap v Source #

class (IsMany a b, Is b a) => Is a b Source #

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

Laws

from is an inverse of to

For all values of b converting from b to a and then converting from a to b produces the original value:

\b -> b == from @a (to @a b)

to is an inverse of from

For all values of a converting from a to b and then converting from b to a produces the original value:

\a -> a == to @a (from @a @b a)

Mathematical relationship

These two laws together establish that to and from form a true isomorphism between types a and b. Note that from is implemented as to from the reverse Is instance, ensuring the symmetry required for isomorphisms.

from equals onfrom

For isomorphic types, both ways of converting should be equivalent:

\a -> from @a @b a == onfrom @a @b a

Testing

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

Instance Definition

For each pair of isomorphic types (A and B) the compiler will require you to define six instances, namely: Is A B and Is B A, IsMany A B and IsMany B A, IsSome A B and IsSome B A.

Instances of Is do not define any functions and serve merely as a statement that the laws are satisfied.

Example: Lazy Text and Text

instance IsSome Data.Text.Lazy.LazyText Data.Text.Text where
  to = LazyText.fromStrict

instance IsSome Data.Text.Text Data.Text.Lazy.LazyText where
  to = LazyText.toStrict

instance IsMany Data.Text.Lazy.LazyText Data.Text.Text

instance IsMany Data.Text.Text Data.Text.Lazy.LazyText

instance Is Data.Text.Lazy.LazyText Data.Text.Text

instance Is Data.Text.Text Data.Text.Lazy.LazyText

Instances

Instances details
Is ByteArray Builder Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndLazyByteStringBuilder

Is ByteArray ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndByteString

Is ByteArray ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndLazyByteString

Is ByteArray ShortByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndShortByteString

Is Int16 Word16 Source # 
Instance details

Defined in LawfulConversions.Relations.Int16AndWord16

Is Int32 Word32 Source # 
Instance details

Defined in LawfulConversions.Relations.Int32AndWord32

Is Int64 Word64 Source # 
Instance details

Defined in LawfulConversions.Relations.Int64AndWord64

Is Int8 Word8 Source # 
Instance details

Defined in LawfulConversions.Relations.Int8AndWord8

Is Word16 Int16 Source # 
Instance details

Defined in LawfulConversions.Relations.Int16AndWord16

Is Word32 Int32 Source # 
Instance details

Defined in LawfulConversions.Relations.Int32AndWord32

Is Word64 Int64 Source # 
Instance details

Defined in LawfulConversions.Relations.Int64AndWord64

Is Word8 Int8 Source # 
Instance details

Defined in LawfulConversions.Relations.Int8AndWord8

Is Builder ByteArray Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndLazyByteStringBuilder

Is Builder ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndLazyByteStringBuilder

Is Builder ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndLazyByteStringBuilder

Is Builder ShortByteString Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringBuilderAndShortByteString

Is ByteString ByteArray Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndByteString

Is ByteString Builder Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndLazyByteStringBuilder

Is ByteString ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndLazyByteString

Is ByteString ShortByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndShortByteString

Is ByteString ByteArray Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndLazyByteString

Is ByteString Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndLazyByteStringBuilder

Is ByteString ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndLazyByteString

Is ByteString ShortByteString Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndShortByteString

Is ShortByteString ByteArray Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndShortByteString

Is ShortByteString Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringBuilderAndShortByteString

Is ShortByteString ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndShortByteString

Is ShortByteString ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndShortByteString

Is Text Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextBuilderAndText

Is Text Text Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndText

Is Text StrictBuilder Source # 
Instance details

Defined in LawfulConversions.Relations.StrictTextBuilderAndText

Is Builder Text Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextBuilderAndText

Is Builder Text Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndLazyTextBuilder

Is Builder StrictBuilder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextBuilderAndStrictTextBuilder

Is Text Text Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndText

Is Text Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndLazyTextBuilder

Is Text StrictBuilder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndStrictTextBuilder

Is StrictBuilder Text Source # 
Instance details

Defined in LawfulConversions.Relations.StrictTextBuilderAndText

Is StrictBuilder Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextBuilderAndStrictTextBuilder

Is StrictBuilder Text Source # 
Instance details

Defined in LawfulConversions.Relations.LazyTextAndStrictTextBuilder

Is Int Word Source # 
Instance details

Defined in LawfulConversions.Relations.IntAndWord

Is Word Int Source # 
Instance details

Defined in LawfulConversions.Relations.IntAndWord

Is a a Source #

Any type is isomorphic to itself.

Instance details

Defined in LawfulConversions.Relations.Any

Is ByteArray [Word8] Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndWord8List

Is Builder [Word8] Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringBuilderAndWord8List

Is ByteString [Word8] Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndWord8List

Is ByteString [Word8] Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndWord8List

Is ShortByteString [Word8] Source # 
Instance details

Defined in LawfulConversions.Relations.ShortByteStringAndWord8List

Is IntSet (Set Int) Source # 
Instance details

Defined in LawfulConversions.Relations.IntSetAndSetOfInt

Is b (ViaIsSome a b) Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

Is (Set Int) IntSet Source # 
Instance details

Defined in LawfulConversions.Relations.IntSetAndSetOfInt

Is [Word8] ByteArray Source # 
Instance details

Defined in LawfulConversions.Relations.ByteArrayAndWord8List

Is [Word8] Builder Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringBuilderAndWord8List

Is [Word8] ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ByteStringAndWord8List

Is [Word8] ByteString Source # 
Instance details

Defined in LawfulConversions.Relations.LazyByteStringAndWord8List

Is [Word8] ShortByteString Source # 
Instance details

Defined in LawfulConversions.Relations.ShortByteStringAndWord8List

Is (Seq a) (Vector a) Source # 
Instance details

Defined in LawfulConversions.Relations.BoxedVectorAndSeq

Is (Seq a) [a] Source # 
Instance details

Defined in LawfulConversions.Relations.ListAndSeq

Is (Vector a) (Seq a) Source # 
Instance details

Defined in LawfulConversions.Relations.BoxedVectorAndSeq

Is (Vector a) [a] Source # 
Instance details

Defined in LawfulConversions.Relations.BoxedVectorAndList

Is [a] (Seq a) Source # 
Instance details

Defined in LawfulConversions.Relations.ListAndSeq

Is [a] (Vector a) Source # 
Instance details

Defined in LawfulConversions.Relations.BoxedVectorAndList

Is (IntMap v) (Map Int v) Source # 
Instance details

Defined in LawfulConversions.Relations.IntMapAndMapOfInt

Is (ViaIsSome a b) b Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

Is (Map Int v) (IntMap v) Source # 
Instance details

Defined in LawfulConversions.Relations.IntMapAndMapOfInt

Combinators

from :: forall b a. IsSome a b => b -> a Source #

Convert a value of a subset type to a superset type, specifying the source subset type first.

Alias to to with the only difference in the argument order.

E.g.,

fromText = from @Text

maybeTo :: forall b a. IsSome a b => a -> Maybe b Source #

Try to convert a value of a superset type to a subset type specifying the target subset type first.

Alias to maybeFrom with the only difference in the argument order.

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

maybeToInt16 :: Int32 -> Maybe Int16
maybeToInt16 = maybeTo @Int16
percent = maybeTo @Percent someDouble

tryFrom :: IsSome a b => e -> a -> Either e b Source #

Like maybeFrom, but returns an Either with the provided error on failure.

Useful for raising custom errors when conversion fails.

tryTo :: forall b a e. IsSome a b => e -> a -> Either e b Source #

Alias to tryFrom, which lets you specify the target type of the conversion first using TypeApplications.

onto :: forall b a. IsMany a b => a -> b Source #

Alias to onfrom, which lets you specify the target type of the conversion first using TypeApplications.

In mathematics onto is another name for Surjective function.

E.g.,

lenientDecodeUtf8 = onto @Text
combineTexts :: Text -> ByteString -> Int -> Text
combineTexts name email height =
  from @StrictTextBuilder $
    "Height of " <> to name <> " is " <> onto (show height) <> " and email is " <> onto email

Optics

isSomePrism :: (IsSome a b, Choice p, Applicative f) => p b (f b) -> p a (f a) Source #

Van-Laarhoven-style Prism, compatible with libraries like "lens" and "optics".

isManyIso :: (IsMany a b, Profunctor p, Functor f) => p b (f b) -> p a (f a) Source #

Van-Laarhoven-style Isomorphism, compatible with libraries like "lens" and "optics".

isIso :: (Is a b, Profunctor p, Functor f) => p b (f b) -> p a (f a) Source #

Van-Laarhoven-style Isomorphism, compatible with libraries like "lens" and "optics".

Instance derivation

Proxy data-types useful for deriving various standard instances using the DerivingVia extension.

newtype ViaIsSome a b Source #

Helper for deriving common instances on types which have an instance of IsSome a using the DerivingVia extension.

E.g.,

newtype Percent = Percent Double
  deriving newtype (Show, Eq, Ord)
  deriving (Read, Arbitrary) via (ViaIsSome Double Percent)

instance IsSome Double Percent where
  to (Percent double) = double
  maybeFrom double =
    if double < 0 || double > 1
      then Nothing
      else Just (Percent double)

In the code above all the instances that are able to construct the values of Percent are automatically derived based on the IsSome Double Percent instance. This guarantees that they only construct values that pass thru the checks defined in maybeFrom.

Constructors

ViaIsSome b 

Instances

Instances details
Is b (ViaIsSome a b) Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

IsMany b (ViaIsSome a b) Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

Methods

onfrom :: b -> ViaIsSome a b Source #

IsSome a b => IsSome a (ViaIsSome a b) Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

Methods

to :: ViaIsSome a b -> a Source #

maybeFrom :: a -> Maybe (ViaIsSome a b) Source #

IsSome b (ViaIsSome a b) Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

Methods

to :: ViaIsSome a b -> b Source #

maybeFrom :: b -> Maybe (ViaIsSome a b) Source #

(IsSome a b, Arbitrary a) => Arbitrary (ViaIsSome a b) Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

Methods

arbitrary :: Gen (ViaIsSome a b) #

shrink :: ViaIsSome a b -> [ViaIsSome a b] #

(IsSome a b, IsString a) => IsString (ViaIsSome a b) Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

Methods

fromString :: String -> ViaIsSome a b #

(IsSome a b, Read a) => Read (ViaIsSome a b) Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

(IsSome a b, Show a) => Show (ViaIsSome a b) Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

Methods

showsPrec :: Int -> ViaIsSome a b -> ShowS #

show :: ViaIsSome a b -> String #

showList :: [ViaIsSome a b] -> ShowS #

(IsSome a b, Eq a) => Eq (ViaIsSome a b) Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

Methods

(==) :: ViaIsSome a b -> ViaIsSome a b -> Bool #

(/=) :: ViaIsSome a b -> ViaIsSome a b -> Bool #

(IsSome a b, Ord a) => Ord (ViaIsSome a b) Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

Methods

compare :: ViaIsSome a b -> ViaIsSome a b -> Ordering #

(<) :: ViaIsSome a b -> ViaIsSome a b -> Bool #

(<=) :: ViaIsSome a b -> ViaIsSome a b -> Bool #

(>) :: ViaIsSome a b -> ViaIsSome a b -> Bool #

(>=) :: ViaIsSome a b -> ViaIsSome a b -> Bool #

max :: ViaIsSome a b -> ViaIsSome a b -> ViaIsSome a b #

min :: ViaIsSome a b -> ViaIsSome a b -> ViaIsSome a b #

Is (ViaIsSome a b) b Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

IsMany (ViaIsSome a b) b Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

Methods

onfrom :: ViaIsSome a b -> b Source #

IsSome (ViaIsSome a b) b Source # 
Instance details

Defined in LawfulConversions.Proxies.ViaIsSome

Methods

to :: b -> ViaIsSome a b Source #

maybeFrom :: ViaIsSome a b -> Maybe b Source #

Testing

isSomeProperties :: (IsSome a b, Eq a, Eq b, Show a, Show b, Arbitrary a, Arbitrary b) => Proxy a -> Proxy b -> [(String, Property)] Source #

Properties testing whether an instance satisfies the laws of IsSome.

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:

spec = do
  describe "IsSome laws" do
    traverse_
      (uncurry prop)
      (isSomeProperties @Int32 @Int16 Proxy Proxy)

isManyProperties :: (IsMany a b, Eq a, Eq b, Show a, Show b, Arbitrary a, Arbitrary b) => Proxy a -> Proxy b -> [(String, Property)] Source #

Properties testing whether an instance satisfies the laws of IsMany.

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:

spec = do
  describe "IsMany laws" do
    traverse_
      (uncurry prop)
      (isManyProperties @String @Text Proxy Proxy)

isProperties :: (Is a b, Eq a, Eq b, Show a, Show b, Arbitrary a, Arbitrary b) => Proxy a -> Proxy b -> [(String, Property)] Source #

Properties testing whether an instance satisfies the laws of Is.

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:

spec = do
  describe "Is laws" do
    traverse_
      (uncurry prop)
      (isProperties @Int32 @Word32 Proxy Proxy)