Safe Haskell | None |
---|---|
Language | Haskell2010 |
This module provides heterogenuous lists. There are a few functions on these lists which are an attempt
to be parallels of the Functor
, Applicative
and Monad
classes,
although these are not part of type classes, and certainly not the above classes because the types don't match.
I believe this sort of package has potential in testing generic libraries.
For example, lets say you have (n)
sets of test data.
And (m)
different functions that work on that data.
And (m)
different "check functions" (perhaps just the functions above but one release back as a control).
Making a complete test case for all this is tricky, because you may be testing different types and the functions you're testing on them may have different results.
You can sometimes get situations where you just have to write (n * m)
test cases.
This approach hopefully makes the work (n + m)
instead.
It probably needs some work but I have included a functional example in the documentation for hap
.
- data HeteroList l where
- (:-) :: a -> HeteroList as -> HeteroList (a ': as)
- Nil :: HeteroList '[]
- (++) :: HeteroList a -> HeteroList b -> HeteroList (a :++ b)
- happend :: HeteroList a -> HeteroList b -> HeteroList (a :++ b)
- class HeteroListConstraintT c a => HeteroListConstraint c a
- class IsHeteroListT a => IsHeteroList a
- type family GetHead a where ...
- type family GetTail a where ...
- type family GetHeteroListParam a where ...
- hconcat :: HeteroListConstraint IsHeteroList a => HeteroList a -> HeteroList (ConcatT a)
- hmap :: HeteroMapConstraint c a b => Poly c -> HeteroList a -> HeteroList b
- hconcatMap :: forall c a b. (HeteroMapConstraint c a b, HeteroListConstraint IsHeteroList b) => Poly c -> HeteroList a -> HeteroList (ConcatT b)
- class HeteroMapConstraintT c a b => HeteroMapConstraint c a b
- hmapfl :: forall f a b c. (HeteroMapConstraint c f b, c ~ WhatsC a, HeteroListConstraint IsHeteroList b) => HeteroList f -> HeteroList a -> HeteroList b
- hap :: forall f a b c. (HeteroMapConstraint c f b, c ~ WhatsC a, HeteroListConstraint IsHeteroList b) => HeteroList f -> HeteroList a -> HeteroList (ConcatT b)
- type family ConcatT a where ...
- toList :: forall a t. IsHomogeneousList a t => HeteroList t -> [a]
- class HeteroListConstraint (Equal a) t => IsHomogeneousList a t
- length :: forall t. HeteroList t -> Int
- type family ListLength t :: Nat where ...
Documentation
data HeteroList l where Source #
Heterogeneous list type. Construct like so:
x = (5 :: Int) :- 'a' :- True :- Nil
(:-) :: a -> HeteroList as -> HeteroList (a ': as) infixr 5 | |
Nil :: HeteroList '[] |
HeteroListConstraint Eq a => Eq (HeteroList a) Source # | |
(HeteroListConstraint Eq a, HeteroListConstraint Ord a) => Ord (HeteroList a) Source # | |
(Show a, Show (ShowRest (HeteroList as))) => Show (HeteroList ((:) * a as)) Source # | |
Show (HeteroList ([] *)) Source # | |
(++) :: HeteroList a -> HeteroList b -> HeteroList (a :++ b) Source #
Append two heterogeneous lists. Of course, as HeteroList
s know their type, this produces a new type.
happend :: HeteroList a -> HeteroList b -> HeteroList (a :++ b) Source #
Synonym for '(++)'.
class HeteroListConstraintT c a => HeteroListConstraint c a Source #
Applies a constraint c
to a type of HeteroList a
.
So you want to write this:
(HeteroListConstraintT c t) => HeteroList t
not
HeteroListConstraintT c (HeteroList t) => HeteroList t
HeteroListConstraintT c a => HeteroListConstraint c a Source # | |
class IsHeteroListT a => IsHeteroList a Source #
Constraint which requires the argument to be a HeteroList
IsHeteroListT a => IsHeteroList a Source # | |
type family GetHead a where ... Source #
Get the type of the first element of a HeteroList
GetHead (HeteroList (a ': _)) = a |
type family GetTail a where ... Source #
Get the type of the tail of a HeteroList
.
GetTail (HeteroList (_ ': as)) = as |
type family GetHeteroListParam a where ... Source #
Gets the types of the HeteroList
. Naturally this is a list of types of type [*]
.
GetHeteroListParam (HeteroList a) = a |
hconcat :: HeteroListConstraint IsHeteroList a => HeteroList a -> HeteroList (ConcatT a) Source #
An analogue to concat
hmap :: HeteroMapConstraint c a b => Poly c -> HeteroList a -> HeteroList b Source #
hconcatMap :: forall c a b. (HeteroMapConstraint c a b, HeteroListConstraint IsHeteroList b) => Poly c -> HeteroList a -> HeteroList (ConcatT b) Source #
class HeteroMapConstraintT c a b => HeteroMapConstraint c a b Source #
This constraints c
, which is intended to be the argument of a Poly
, to be a constraint which allows one
to map between the two HeteroList
s of type a
and b
HeteroMapConstraintT c a b => HeteroMapConstraint c a b Source # | |
hmapfl :: forall f a b c. (HeteroMapConstraint c f b, c ~ WhatsC a, HeteroListConstraint IsHeteroList b) => HeteroList f -> HeteroList a -> HeteroList b Source #
Applies every function in the HeteroList
of Poly
s in the first argument to the HeteroList
which is the second argument.
This is much like hap
except the result list is not "flattened" by hconcat
hap :: forall f a b c. (HeteroMapConstraint c f b, c ~ WhatsC a, HeteroListConstraint IsHeteroList b) => HeteroList f -> HeteroList a -> HeteroList (ConcatT b) Source #
This is the analogue of ap
, or 'Control.Applicative.<*>. Arguments are the same as hmapfl
, but the result is flattened.
Here's an example usage:
>>>
triple = Poly @((IsHomoFunc 1) &&& ((Arg 0) `IxConstrainBy` Num)) (*3)
>>>
compareZero = Poly @((IsFunc 1) &&& ((Arg 0) `IxConstrainBy` (Num &&& Ord)) &&& ((Result 1) `IxIs` Ordering)) (`compare` 0)
>>>
greaterThanZero = Poly @((IsFunc 1) &&& ((Arg 0) `IxConstrainBy` (Num &&& Ord)) &&& ((Result 1) `IxIs` Bool)) (> 0)
>>>
f = triple :- compareZero :- greaterThanZero :- Nil
>>>
x = (42 :: Int) :- (-100 :: Float) :- (22 % 7 :: Rational) :- Nil
>>>
f `hap` x
[126, -300.0, 66 % 7, GT, LT, GT, True, False, True]
Note that
type family ConcatT a where ... Source #
The type of a concatenated list. Note, like HeteroListConstraintT
you need to apply this type function to
the parameter to HeteroList
.
ConcatT (HeteroList a ': as) = a :++ ConcatT as | |
ConcatT '[] = '[] |
toList :: forall a t. IsHomogeneousList a t => HeteroList t -> [a] Source #
Naturally, if (and only if) a HeteroList
is actually homogeneous, we can turn it into an ordinary list.
class HeteroListConstraint (Equal a) t => IsHomogeneousList a t Source #
IsHomogeneousList a t
constraints a 'HeteroList t' to have elements only of type a.
i.e.
IsHomogeneousList Int t => HeteroList t
means the HeteroList
only has elements of type Int
.
HeteroListConstraint (Equal a) t => IsHomogeneousList a t Source # | |
length :: forall t. HeteroList t -> Int Source #
Length of a HeteroList
. I'm not sure if this can be done in constant time as the type defines the length,
but currently it just does the usual traverse the list and count.
type family ListLength t :: Nat where ... Source #
Type level length the paramter of a HeteroList
ListLength '[] = 0 | |
ListLength (_ ': as) = 1 + ListLength as |