\subsubsection{HList} \label{sec-HList} \index{HList (package)} {\bf Package} \begin{verbatim} import HList :: * ; \end{verbatim} {\bf Description} The \te{HList} package defines a datatype \te{HList} which stores a list of data of different types. The package also provides typeclasses and functions to perform various list operations on the \te{HList} type. The primitive data structures for an \te{HList} are \te{HNil} and the polymorphic \te{HCons}. The various functions are provided by typeclasses, one for each function. The package defines a typeclass \te{Gettable} for finding (\te{getIt}) and replacing (\te{putIt}) items in an \te{HList}. This requires that all the items in the \te{HList} are different types. If two types are the same, they must be disambiguated by encapsulating at least one of them (but preferably each of them) in a new struct type. The functions of the \te{Gettable} typeclass require that the \te{HList} be flat (no nested \te{HLists}) and well-formed (terminating in \te{HNil}). That is, the target of a recursive search must be either the complete \te{hHead} or found within the \te{hTail}. {\bf Types and type classes} The \te{HList} packages defines a typeclass \te{HList}: \begin{verbatim} typeclass HList#(type l); \end{verbatim} The \te{HNil} datatype defines a nil instance, the empty set. An \te{HList} is usually terminated by a \te{HNil}. \begin{verbatim} typedef struct {} HNil deriving (Eq); \end{verbatim} The \te{HCons} datatype is a structure with two members, a head of datatype \te{e} and a tail of datatype \te{l}. \begin{verbatim} typedef struct { e hd; l tl; } HCons#(type e, type l) deriving (Eq); \end{verbatim} {\bf Functions} The various functions for heterogenous lists are provided by typeclasses, one for each functions. \index{HHead@\te{HHead} (typeclass)} \index[function]{HList!HHead} \begin{tabular}{|p{1 in}|p{4.5 in}|} \hline & \\ \te{HHead} & Returns the first element of the list.\\ \cline{2-2} &\begin{libverbatim} typeclass HHead#(type l, type h) dependencies (l determines h); function h hHead(l x); endtypeclass instance HHead#(HCons#(e, l), e); \end{libverbatim} \\ \hline \end{tabular} \index{HTail@\te{HTail} (typeclass)} \index[function]{HList!HTail} \begin{tabular}{|p{1 in}|p{4.5 in}|} \hline & \\ \te{HTail} & Returns the tail element from the list. \\ \cline{2-2} &\begin{libverbatim} typeclass HTail#(type l, type lt) dependencies (l determines lt); function lt hTail(l xs); endtypeclass instance HTail#(HCons#(e, l), l); \end{libverbatim} \\ \hline \end{tabular} \index{HLength@\te{HLength} (typeclass)} \index[function]{HList!HLength} \begin{tabular}{|p{1 in}|p{4.5 in}|} \hline & \\ \te{HLength} &Returns a numeric value with the length of the list. For a \te{HNil}, will return 0. \\ \cline{2-2} &\begin{libverbatim} typeclass HLength#(type l, numeric type n); endtypeclass instance HLength#(HNil, 0); instance HLength#(HCons#(e, l), nPlus1) provisos (HLength#(l, n), Add#(n,1,nPlus1)); \end{libverbatim} \\ \hline \end{tabular} \index{HAppend@\te{HAppend} (typeclass)} \index[function]{HList!HAppend} \begin{tabular}{|p{1 in}|p{4.5 in}|} \hline & \\ \te{HAppend} & Appends two lists, returning the combined list. The elements do not have to be of the same data type. The combined list will be of type \te{l2}, and will contain all the elements of \te{xs} followed in order by all the elements of \te{ys}.\\ \cline{2-2} &\begin{libverbatim} typeclass HAppend#(type l, type l1, type l2) dependencies ((l, l1) determines l2); function l2 hAppend(l xs, l1 ys); instance HAppend#(HNil, l, l); instance HAppend#(HCons#(e, l), l1, HCons#(e, l2)) provisos (HList#(l), HAppend#(l, l1, l2)); \end{libverbatim} \\ \hline \end{tabular} \index{HSplit@\te{HSplit} (typeclass)} \index[function]{HList!hSplit} \begin{tabular}{|p{1 in}|p{4.5 in}|} \hline & \\ \te{HSplit} & The \te{hSplit} function takes an \te{HList} of type \te{l} and returns a \te{Tuple2} of two \te{HLists}. This function is the inverse of \te{hAppend}.\\ \cline{2-2} &\begin{libverbatim} typeclass HSplit#(type l, type l1, type l2); function Tuple2#(l1,l2) hSplit(l xs); endtypeclass instance HSplit#(HNil, HNil, HNil); instance HSplit#(l, HNil, l); instance HSplit#(HCons#(hd,tl), HCons#(hd,l3), l2) provisos (HSplit#(tl,l3,l2)); \end{libverbatim} \\ \hline \end{tabular} \index{Gettable@\te{Gettable} (typeclass)} \index[function]{HList!Gettable} \begin{tabular}{|p{1 in}|p{4.5 in}|} \hline & \\ \te{Gettable} &This typeclass is for finding (\te{getIt}) and replacing (\te{putIt}) a particular element in an \te{HList}. All items in the \te{HList} must be of different types. If two types are the same, they should be disambiguated by encapsulating at least one of them (and preferably both of them) in a new struct type.\\ \cline{2-2} &\begin{libverbatim} typeclass Gettable#(type c1, type c2); function c2 getIt(c1 x); function c1 putIt(c1 x, c2 y); endtypeclass instance Gettable#(HCons#(t1, t2), t1); instance Gettable#(HCons#(t1, t2), t3) provisos (Gettable#(t2, t3)); \end{libverbatim} \\ \hline \end{tabular} {\bf Small Lists} The \te{HList} packcage provides type definitions for small lists, ranging from 1 element to 8 elements, along with constructor functions to build the lists. {\bf HList1} \begin{verbatim} typedef HCons#(t, HNil) HList1#(type t); function HList1#(t1) hList1(t1 x1) = hCons(x1, hNil); \end{verbatim} {\bf HList2} \begin{verbatim} typedef HCons#(t1, HCons#(t2, HNil)) HList2#(type t1, type t2); function HList2#(t1, t2) hList2(t1 x1, t2 x2) = hCons(x1, hCons(x2, hNil)); \end{verbatim} {\bf HList3} \begin{verbatim} typedef HCons#(t1, HCons#(t2, HCons#(t3, HNil))) HList3#(type t1, type t2, type t3); function HList3#(t1, t2, t3) hList3(t1 x1, t2 x2, t3 x3) = hCons(x1, hCons(x2, hCons(x3, hNil))); \end{verbatim} {\bf HList4} \begin{verbatim} typedef HCons#(t1, HCons#(t2, HCons#(t3, HCons#(t4, HNil)))) HList4#(type t1, type t2, type t3, type t4); function HList4#(t1, t2, t3, t4) hList4(t1 x1, t2 x2, t3 x3, t4 x4) = hCons(x1, hCons(x2, hCons(x3, hCons(x4, hNil)))); \end{verbatim} {\bf HList5} \begin{verbatim} typedef HCons#(t1, HCons#(t2, HCons#(t3, HCons#(t4, HCons#(t5, HNil))))) HList5#(type t1, type t2, type t3, type t4, type t5); function HList5#(t1, t2, t3, t4, t5) hList5(t1 x1, t2 x2, t3 x3, t4 x4, t5 x5) = hCons(x1, hCons(x2, hCons(x3, hCons(x4, hCons(x5, hNil))))); \end{verbatim} {\bf HList6} \begin{verbatim} typedef HCons#(t1, HCons#(t2, HCons#(t3, HCons#(t4, HCons#(t5, HCons#(t6, HNil)))))) HList6#(type t1, type t2, type t3, type t4, type t5, type t6); function HList6#(t1, t2, t3, t4, t5, t6) hList6(t1 x1, t2 x2, t3 x3, t4 x4, t5 x5, t6 x6) = hCons(x1, hCons(x2, hCons(x3, hCons(x4, hCons(x5, hCons(x6, hNil)))))); \end{verbatim} {\bf HList7} \begin{verbatim} typedef HCons#(t1, HCons#(t2, HCons#(t3, HCons#(t4, HCons#(t5, HCons#(t6, HCons#(t7, HNil))))))) HList7#(type t1, type t2, type t3, type t4, type t5, type t6, type t7); function HList7#(t1, t2, t3, t4, t5, t6, t7) hList7(t1 x1, t2 x2, t3 x3, t4 x4, t5 x5, t6 x6, t7 x7) = hCons(x1, hCons(x2, hCons(x3, hCons(x4, hCons(x5, hCons(x6, hCons(x7, hNil))))))); \end{verbatim} {\bf HList8} \begin{verbatim} typedef HCons#(t1, HCons#(t2, HCons#(t3, HCons#(t4, HCons#(t5, HCons#(t6, HCons#(t7, HCons#(t8, HNil)))))))) HList8#(type t1, type t2, type t3, type t4, type t5, type t6, type t7, type t8); function HList8#(t1, t2, t3, t4, t5, t6, t7, t8) hList8(t1 x1, t2 x2, t3 x3, t4 x4, t5 x5, t6 x6, t7 x7, t8 x8) = hCons(x1, hCons(x2, hCons(x3, hCons(x4, hCons(x5, hCons(x6, hCons(x7, hCons(x8, hNil)))))))); \end{verbatim}