Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The type error is from this chain of logic: the 'ui' has 'structui' outermost and 'structUI :: (FieldList tk l) =>' needs the '(FieldList tk l)' where 'tk' and 'l' must match the type signature you wrote for 'ui'.</p> <p>Everything is, individually, polymorphic in the type variable 'tk'. </p> <p>The type checker gives a different tk0 to the argument to structui/fcons and just because you have an instance with matching tk's does not mean that I will not come along and make a FieldList instance with distinct tk's. Thus the type checker is stuck.</p> <p>Here is how I can fix this for the type checker:</p> <pre><code>-- Use this instance instead of the one you wrote instance (UITK tk, FieldList tk l, tk ~ tk') =&gt; FieldList tk (HCons (UI tk' a) l) where type StructV tk (HCons (UI tk' a) l) = (HCons a (StructV tk l)) -- Now this works :) ui :: (UITK tk) =&gt; (UI tk (HCons String (HCons Int HNil))) ui = structUI (fcons stringEntry (fcons intEntry HNil )) </code></pre> <p>The replacement instance matches all possible combinations of tk and tk', then requires they be the same. No one can come along and write another such instance without overlapping.</p> <p><strong>Responding to timbod's comment:</strong> Consider this code, note that (toEnum 97)::Char is 'a'</p> <pre><code>class TwoParam a b where combine :: a -&gt; b -&gt; (a,b) combine = (,) instance TwoParam c c t1 :: (TwoParam Char b) =&gt; Char -&gt; b -&gt; (Char,b) t1 = combine main = print (t1 'a' (toEnum 97)) </code></pre> <p>This fails with the message:</p> <blockquote> <pre><code>No instance for (TwoParam Char b0) arising from a use of `t1' Possible fix: add an instance declaration for (TwoParam Char b0) In the first argument of `print', namely `(t1 'a' (toEnum 98))' In the expression: print (t1 'a' (toEnum 98)) In an equation for `main': main = print (t1 'a' (toEnum 98)) Failed, modules loaded: none. </code></pre> </blockquote> <p>Why? The type checker infers that (toEnum 98) has some Enum type, and this might be Char, but it will not make the inference that it must be Char. The type checker will not match (toEnum 97) to Char even though the only available instance of (TwoParam Char b) would require matching b with Char. The compiler is correct here because I could later write another instance:</p> <pre><code>-- instance TwoParam Char Integer </code></pre> <p>With this second (overlapping) instance it is no longer obvious which instance ought to be chosen. The solution is to use the above 'trick':</p> <pre><code>-- instance (c ~ d) =&gt; TwoParam c d </code></pre> <p>The type checker only looks at the 'TwoParam c d' when choosing an instance, and this matches everything. Then it tries to satisfy the constraint </p> <blockquote> <p>Char ~ typeOf (fromEnum 98)</p> </blockquote> <p>which will succeed. With the trick 'main' prints ('a','a')</p>
    singulars
    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.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      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