finitary-derive-2.1.0.0: Flexible and easy deriving of type classes for finitary types.
Copyright (C) Koz Ross 2019 GPL version 3.0 or later koz.ross@retro-freedom.nz Experimental GHC only None Haskell2010

Data.Finitary.PackInto

Description

This allows us to 'borrow' implementations of certain type classes from 'larger' finitary types for 'smaller' finitary types. Essentially, for any types a and b, if both a and b are Finitary and Cardinality a <= Cardinality b, the set of indexes for a is a subset (strictly speaking, a prefix) of the set of indexes for b. Therefore, we have an injective mapping from a to b, whose preimage is also injective, witnessed by the function fromFinite . toFinite in both directions. When combined with the monotonicity of toFinite and fromFinite, we can operate on inhabitants of b in certain ways while always being able to recover the 'equivalent' inhabitant of a.

On this basis, we can 'borrow' both Unbox and Storable instances from b. This is done by way of the PackInto a b type; here, a is the type to which instances are being 'lent' and b is the type from which instances are being 'borrowed'. PackInto a b does not store any values of type a - construction and deconstruction of PackInto performs a conversion as described above.

If an existing Finitary type exists with desired instances, this encoding is the most flexible and efficient. Unless you have good reasons to consider something else (such as space use), use this encoding. However, its usefulness is conditional on a suitable 'packing' type existing of appropriate cardinality. Additionally, if Cardinality a < Cardinality b, any PackInto a b will waste some space, with larger cardinality differences creating proportionately more waste.

Synopsis

# Documentation

data PackInto (a :: Type) (b :: Type) Source #

An opaque wrapper, representing values of type a as 'corresponding' values of type b.

#### Instances

Instances details

pattern Packed :: forall (b :: Type) (a :: Type). (Finitary a, Finitary b, Cardinality a <= Cardinality b) => PackInto a b -> a Source #

To provide (something that resembles a) data constructor for PackInto, we provide the following pattern. It can be used like any other data constructor:

import Data.Finitary.PackInt

anInt :: PackInto Int Word
anInt = Packed 10

isPackedEven :: PackInto Int Word -> Bool
isPackedEven (Packed x) = even x

Every pattern match, and data constructor call, performs a re-encoding by way of fromFinite . toFinite on b and a respectively. Use with this in mind.