Short answer: There is no good way of doing what you want. <br>This is actually one of my biggest annoyances with haskell (right up there with disallowing infinite types). They are many techniques that work better or worse depending on the application, but non are very satisfactory IMO. <br>
Your typeclass solution(or some variant of) is pretty much your best option. If you&#39;re careful about how you define your datatype and classes you can avoid the type families and such, but the whole point is to not have to be careful.<br>
If your types are fixed (which is usually true as long as you&#39;re not
using existentials) you might be able to get away with using -XDisambiguateFieldRecords<br><br>If you want anything better you&#39;re probably going to have to use some form of preprocessor (like OHaskell). <br><br><br>Supposedly OCaml has an OO feature that does this but I haven&#39;t tried it out.<br>
<br>I would suspect that the reason why haskell doesn&#39;t provide duck typeing on record fields is that analisys for optimizations is much more complicated (as it currently stands, records are nothing but sugar on top of algeraic datatypes). <br>
You can end up with all sorts of weird things with duck typeing on record fields, like unnamed datatypes. For example:<br><br>(using class constraint style to inidicate a record field restriction for lack of a better syntax)<br>
setPosition :: (position a) =&gt;Vector -&gt; a -&gt; a<br>setPosition v x = x { position = v }<br><br>translate :: (position a) =&gt;Vector -&gt; a -&gt; a<br>translate v x = x { position = v + (position x) }<br><br>getPosition :: (position a) =&gt; a -&gt; Vector<br>
getPosition x = position x<br><br>result :: Vector<br>result = getPosition $ translate someVector $ setPosition someOtherVector<br><br>The type variable &#39;a&#39; in these functions is never fixed to a specific type, and it actually doesn&#39;t need to be. The compiler would just have to invent a suitable one (a type with only the field &#39;position&#39; of type Vector). <br>
<br>Maybe someday haskell will finially implement good, clean, duck typeable, record functionality. I will be waiting...<br><br>- Job<br><br><br><div class="gmail_quote">On Fri, Sep 25, 2009 at 9:54 AM, Peter Verswyvelen <span dir="ltr">&lt;<a href="mailto:bugfact@gmail.com">bugfact@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Haskell&#39;s records are a bit annoying, and type-classes often group together too many methods, which means you make early decisions about future unknown requirements, and IMO you always get it wrong :-)<div>
<div><br>After having read an email in the cafe about the Noop language &amp; Self language, I realized that what I really would like to have is &quot;strong duck typing&quot; on records (or is it called structural subtyping? or prototype-based-objects? or something like that)<div>

<div><br>For example (silly example full of inaccuracies, but you get the picture):<br><br><font face="&#39;courier new&#39;, monospace">class HasPosition a where<br>   position :: a -&gt; Point<br>
   withPosition :: Point -&gt; a -&gt; a<br><br>class HasVelocity a where<br>   velocity :: a -&gt; Vector<br>   withVelocity :: Vector -&gt; a -&gt; a<br></font><br>which we really should write as<br><br><font face="&#39;courier new&#39;, monospace">field HasPosition :: Point<br>

field HasVelocity :: Vector</font><br><br>And then </div><div><br><font face="&#39;courier new&#39;, monospace">record IsKinetic :: HasPosition HasVelocity<br></font><br>suppose we write a function like<br>
<br><font face="&#39;courier new&#39;, monospace">kineticEulerStep dt k = withPosition (position k .+^ dt *^ velocity k) k<br></font><br>kineticEulerStep will work on any type a that HasPosition and HasVelocity, and would get inferred signature<br>

<br><font face="&#39;courier new&#39;, monospace">kineticEulerStep :: IsKinetic a =&gt; Float -&gt; a -&gt; a<br></font><br>which is identical to<br><br><font face="&#39;courier new&#39;, monospace">kineticEulerStep :: (HasPosition a, HasVelocity a) =&gt; Float -&gt; a -&gt; a<br>

</font><br>So basically kineticEulerStep accepts anything that HasPosition and HasVelocity, whatever it is.<br><br>So if it walks like a duck and ..., then it is a duck, but statically known... <br><br>We could also do<br>

<br><font face="&#39;courier new&#39;, monospace">field HasForce :: Vector<br>field HasMass :: Float<br><br>record IsDynamic :: IsKinetic HasForce HasMass<br><br>acceleration d = force d ^/ mass d<br>
withAcceleration a d = withForce (a ^* mass d) d<br><br>dynamicEulerStep dt d = withVelocity (velocity d ^+^ dt *^ acceleration d)<br></font><br>Of course you would also need type families to be really correct since Vector, Point, etc should also be parametrized.</div>

<div><br></div><div>And really kineticEulerStep might also work on something that HasVelocity and HasAcceleration (since the code in dynamicEulerStep is almost the same as kineticEulerStep), so better abstraction might be needed.</div>

<div><br></div><div><div>I&#39;m not sure what kind of overhead a system like this would have in Haskell, since I suspect the many dictionaries are often not optimized away.</div><div><br></div></div><div>I think for Haskell prime,<a href="http://repetae.net/recent/out/classalias.html" target="_blank"> something like this was suggested</a>, but is was rejected?</div>

<div><div><br>Languages like OCaml and <a href="http://haxe.org/manual/2_types" target="_blank">haXe</a> also provide a similar feature?</div><div><div><br></div><div>I would like to collect ways of doing this in Haskell, without boilerplate, and preferably without runtime overhead.</div>

<div><br></div><div>I remember reading OOHaskell a while time ago, and while I didn&#39;t understand a lot of it, I recall it also was doing a similar thing, but since the compiler lacks native support, the error messages you get most likely make it impossible to figure out what is going wrong. I think Grapefruit&#39;s Records, HList, Data.Accessor, etc.. might also work.</div>

<div><br></div><div>Any guidelines and comments regarding &quot;strong duck typing&quot;/&quot;structural subtyping&quot; are very welcome, since the lack of this is the only reason why I would prefer a dynamic language over a static one.</div>

<div><br></div><div>Thanks a lot,</div><div>Peter Verswyvelen</div><div><br></div></div></div></div></div></div>
<br>_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">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>
<br></blockquote></div><br>