Hi,<br><br>I&#39;ve been fidgeting with a fixed-length list library, for things like 3d vectors/points, rgba tuples, etc. The data type is<br><br>data a :. b = (:.) a b<br>&nbsp; deriving (everything reasonable)<br><br>infixr :.<br>

<br>Nothing in that type specifies that for the partially instantiated type t1:.t2:.t3, t1 and t2 should be equal. (Like Int:.Int:.() for a 2D integer point.) But t1 and t2 will always will be equal, at least I want them to always be equal, and everything useful I can think of needs them to be equal.&nbsp; (Note I won&#39;t actually store things in these data types. This is just a way of defining operations. Packed arrays and vectors will be converted to/from these types in a stream-fusioney kind of way. That&#39;s the plan, at least.)<br>

<br>Anyway, I don&#39;t need to force them to be equal because all of the functions for these list-like things come in the form of classes, and those classes have fundeps, and the fundeps let me enforce type constraints.&nbsp; The problem I&#39;m having is making these constraints work nicely with inference. I&#39;m not sure exactly whats going on, which is why I&#39;m asking the list. For an example, folding:<br>

<br>-- the fold function/class<br>class Fold a v | v -&gt; a where<br>&nbsp; fold&nbsp; :: (a -&gt; a -&gt; a) -&gt; v -&gt; a<br>&nbsp; foldl :: (b -&gt; a -&gt; b) -&gt; b -&gt; v -&gt; b<br>&nbsp; foldr :: (a -&gt; b -&gt; b) -&gt; b -&gt; v -&gt; b<br>

<br>-- base case of the recursion, () is like []<br>instance Fold a (a:.()) where<br>&nbsp; fold&nbsp; f&nbsp;&nbsp; (a:._) = a <br>&nbsp; foldl f z (a:._) = f z a<br>&nbsp; foldr f z (a:._) = f a z<br><br>-- inductive case. Pick one of the &quot;instance&quot; declarations below...<br>


instance Fold a (a:.u) =&gt; Fold a (a:.a:.u) where -- I1<br>instance Fold a (a2:.u) =&gt; Fold a (a:.a2:.u) where -- I2<br>&nbsp; fold&nbsp; f&nbsp;&nbsp; (a:.v) = f a (fold f v)<br>&nbsp; foldl f z (a:.v) = f (foldl f z v) a<br>&nbsp; foldr f z (a:.v) = f a (foldr f z v)<br>

<br><br>Now, both of those instance declarations work. The first one (I1) specifies that all of the list elements should be the same type, &quot;a&quot;. The second (I2) doesn&#39;t say that right away, because one is &#39;a&#39; and the other is &#39;a2.&#39; However the fundep (v-&gt;a) will force a and a2 to match, so from orbit the two instances appear the same. In practice, I1 does not cause the type checker to infer the type of list elements, while I2 does. So, in ghci, if you do <br>

<br>foldr (:) [] (1:.2:.3:.())<br><br>With I1 you&#39;ll get an error like &quot;no instance for Fold a (t :. t1 :. t2 :. ())..&quot; But with I2, it will infer 1 2 and 3 to all be of type &quot;Num a =&gt; a&quot; and will evaluate the expression to [1,2,3]. <br>

<br>So the question is &quot;Why?&quot;&nbsp; For simple things like fold, map, etc., I can massage the instance declarations so that the type checker infers things for me, but for more complicated recursions, I&#39;m having trouble. (For example, computing determinants by minor expansion. Not the most efficient way I know, but if I can&#39;t figure that out there&#39;s no hope for Gaussian elimination.) The functions work, its just the inference that isn&#39;t working. I&#39;m forced to annotate things, or at least ensure that the types of the arguments can be inferred from someplace else.<br>

<br>Scott<br>