To reuse a favorite word, I think that any implementation that distinguishes &#39;a -&gt; b, a -&gt; c&#39; from &#39;a -&gt; b c&#39; is broken. :)<br>It does not implement FD, but something else.&nbsp; Maybe this something else is useful, but if one of the forms is strictly more powerful than the other then I don&#39;t see why you would ever want the less powerful one.<br>
<br>&nbsp; -- Lennart<br><br><div class="gmail_quote">On Thu, Apr 17, 2008 at 7:06 AM, Martin Sulzmann &lt;<a href="mailto:martin.sulzmann@gmail.com">martin.sulzmann@gmail.com</a>&gt; wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="Ih2E3d">Mark P Jones wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
Martin Sulzmann wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
We&#39;re also looking for (practical) examples of &quot;multi-range&quot; functional dependencies<br>
<br>
class C a b c | c -&gt; a b<br>
<br>
Notice that there are multiple (two) parameters in the range of the FD.<br>
<br>
It&#39;s tempting to convert the above to<br>
<br>
class C a b c | c -&gt; a, c -&gt; b<br>
<br>
but this yields a weaker (in terms of type improvement) system.<br>
</blockquote>
<br>
I agree with Iavor.<br>
<br>
In fact, the two sets of dependencies that you have given here<br>
are provably equivalent, so it would be decidedly odd to have<br>
a &quot;type improvement&quot; system that distinguishes between them.<br>
<br>
</blockquote>
<br></div>
Consider<br>
<br>
class C a b c | a -&gt; b, a -&gt; c<br>
<br>
instance C a b b =&gt; C [a] [b] [b]<br>
<br>
Suppose we encounter the constraint<br>
<br>
C [x] y z<br>
<br>
What results can we expect from type improvement?<br>
<br>
1) Single-range non-full FDs in GHC following the FD-CHR formulation:<br>
<br>
The first FD C a b c | a -&gt; b in combination with<br>
the instance head C [a] [b] [b] will yield<br>
<br>
C [x] y z improved by y = [b1] for some b1<br>
<br>
A similar reasoning yields<br>
<br>
C [x] y z improved by z = [b2] for some b2<br>
<br>
So, overall we get<br>
<br>
C [x] y z improved by y= [b1] and z = [b2]<br>
<br>
Unfortunately, we couldn&#39;t establish that b1 and b2 are equal.<br>
Hence, we can *not* apply the instance.<br>
<br>
2) Alternative design:<br>
<br>
We could now argue that the improvement implied by the FD<br>
is only applicable if we are in the &quot;right&quot; context.<br>
<br>
That is,<br>
C [x] y z doesn&#39;t yield any improvement because<br>
the context y is still underspecified (doesn&#39;t match<br>
the instance).<br>
<br>
In case of &nbsp;C [x] [y] z we get z = [y]<br>
(and C [x] z [y] yields z = [y])<br>
<br>
<br>
3) Multi-range FDs<br>
<br>
Consider<br>
<br>
class C a b c | a -&gt; b c<br>
<br>
instance C a b b =&gt; C [a] [b] [b]<br>
<br>
This time it&#39;s straightforward.<br>
<br>
C [x] y z yields the improvement y = [b] and z = [b]<br>
which then allows us to apply the instance.<br>
<br>
4) Summary.<br>
<br>
With multi-range FDs we can derive &quot;more&quot; improvement.<br>
<br>
 &nbsp; &nbsp;C [x] y z &nbsp; yields y = [b] and z = [b]<br>
<br>
Based on the FD-CHR formulation, for the single-range FD case we get<br>
<br>
 &nbsp; &nbsp;C [x] y z yields y = [b1] and z = [b2]<br>
<br>
which is clearly weaker.<br>
<br>
The alternative design is even weaker, from C [x] y z we can derive<br>
any improvement.<br>
<br>
So, I conclude that in the Haskell type improvement context<br>
there&#39;s clearly a difference among single-range and multi-range FDs.<br>
<br>
Of course, we could define multi-range FDs in terms of single-range FDs<br>
which then trivially solves the &quot;equivalence&quot; problem (but some user<br>
may be disappointed that their multi-range FDs yield weaker improvement).<br>
<br>
Thanks for your pointers below but I believe that FDs in the Haskell context<br>
can be quite different from FDs in the database context.<br><font color="#888888">
<br>
- Martin</font><div class="Ih2E3d"><br>
<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
While you&#39;re looking for unusual examples of fundeps, you<br>
might also want to consider things like:<br>
<br>
 &nbsp;class C a b c | a -&gt; b, b -&gt; c<br>
<br>
Note that this is subtly different from a -&gt; b c because<br>
<br>
 &nbsp;{a -&gt; b, b -&gt; c} &nbsp;|= &nbsp;{a -&gt; b c}<br>
<br>
while the reverse does not hold. &nbsp;Instead of type classes,<br>
I&#39;ll give you some more down-to-earth examples of relations<br>
that satisfy these dependencies:<br>
<br>
 &nbsp;{Paper, Conference, Year}<br>
 &nbsp;{Professor, University, Country}<br>
 &nbsp;{Person, FavoriteFood, FoodGroup}<br>
 &nbsp;...<br>
<br>
For further insight, you might want to take a look at the theory<br>
of relational databases to see how functional dependencies are<br>
used there. &nbsp;In that context, some sets of dependencies (such<br>
as {a -&gt; b, b -&gt; c}) can be interpreted as indicators of bad<br>
design. &nbsp;This, in turn, might give you some ideas about the kinds<br>
of dependencies you can expect to encounter in well-designed<br>
Haskell code. &nbsp;(Of course, you might still find examples in other<br>
Haskell code of dependencies that would make a database person<br>
wince :-)<br>
<br>
</blockquote>
<br></div><div><div></div><div class="Wj3C7c">
_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org" target="_blank">Haskell-Cafe@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
</div></div></blockquote></div><br>