Note that there are some explanatory texts on larger screens.

plurals
  1. POHow can I make heterogeneous lists (aka HLists) with constrained elements?
    primarykey
    data
    text
    <p>I've been experimenting with using type families to abstract UI toolkits. I've come unstuck as I try to make use of HLists (http://homepages.cwi.nl/~ralf/HList/) to improve the API.</p> <p>My API initially looked something like this:</p> <pre><code>{-# LANGUAGE TypeFamilies #-} class UITK tk where data UI tk :: * -&gt; * stringEntry :: (UITK tk) =&gt; UI tk String intEntry :: (UITK tk) =&gt; UI tk Int tuple2UI :: (UI tk a,UI tk b) -&gt; (UI tk (a,b)) tuple3UI :: (UI tk a,UI tk b,UI tk c) -&gt; (UI tk (a,b,c)) tuple4UI :: (UI tk a,UI tk b,UI tk c,UI tk d) -&gt; (UI tk (a,b,c,d)) ui :: (UITK tk) =&gt; (UI tk (String,Int)) ui = tuple2UI (stringEntry,intEntry) </code></pre> <p>This works, but the UI combiner works on tuples, and so I need a different function for each tuple size. I thought I could make use of something like HLists, but either it's not possible, (or hopefully) I just lack the necessary type-fu.</p> <p>Here's my attempt:</p> <pre><code>{-# LANGUAGE TypeFamilies,FlexibleInstances,MultiParamTypeClasses #-} -- A heterogeneous list type data HNil = HNil deriving (Eq,Show,Read) data HCons e l = HCons e l deriving (Eq,Show,Read) -- A list of UI fields, of arbitrary type, but constrained on their -- tk parameter. The StructV associated type captures the return -- type of the combined UI class (UITK tk) =&gt; FieldList tk l where type StructV tk l instance (UITK tk) =&gt; FieldList tk HNil where type StructV tk HNil = HNil instance (UITK tk, FieldList tk l) =&gt; FieldList tk (HCons (UI tk a) l) where type StructV tk (HCons (UI tk a) l) = (HCons a (StructV tk l)) fcons :: (UITK tk, FieldList tk l) =&gt; UI tk a -&gt; l -&gt; HCons (UI tk a) l fcons = HCons -- Now the abstract ui toolkit definition class UITK tk where data UI tk :: * -&gt; * stringEntry :: (UITK tk) =&gt; UI tk String intEntry :: (UITK tk) =&gt; UI tk Int structUI :: (FieldList tk l) =&gt; l -&gt; (UI tk (StructV tk l)) -- this doesn't work :-( ui :: (UITK tk) =&gt; (UI tk (HCons String (HCons Int HNil))) ui = structUI (fcons stringEntry (fcons intEntry HNil )) </code></pre> <p>The definition at the end gives me several errors, the first of which is:</p> <pre><code>Z.hs:38:6: Could not deduce (FieldList tk (HCons (UI tk0 String) (HCons (UI tk1 Int) HNil))) arising from a use of `structUI' from the context (UITK tk) bound by the type signature for ui :: UITK tk =&gt; UI tk (HCons String (HCons Int HNil)) at Z.hs:(38,1)-(40,21) Possible fix: add (FieldList tk (HCons (UI tk0 String) (HCons (UI tk1 Int) HNil))) to the context of the type signature for ui :: UITK tk =&gt; UI tk (HCons String (HCons Int HNil)) or add an instance declaration for (FieldList tk (HCons (UI tk0 String) (HCons (UI tk1 Int) HNil))) In the expression: structUI (fcons stringEntry (fcons intEntry HNil)) In an equation for `ui': ui = structUI (fcons stringEntry (fcons intEntry HNil)) </code></pre> <p>Without completely understanding this, I think I can see at least one of the problems. I'm not successfully informing the compiler that the 3 tk type parameters are all the same type (ie it refers to tk, tk0, tk1) above. I don't understand this - my fcons constructor is intended to keep the UI tk parameters consistent for the constructed HList.</p> <p>This is my first experience with type families and multi-parameter types classes, so it's likely I'm missing something fundamental.</p> <p>Is is possible to construct heterogeneous lists with constrained elements? Where am I going wrong?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload