<br><div class="gmail_quote">On Sun, Dec 9, 2012 at 10:14 PM, Ashley Yakeley <span dir="ltr">&lt;<a href="mailto:ashley@semantic.org" target="_blank">ashley@semantic.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="im">On 07/12/12 02:19, Edward Kmett wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I am happy to announce the release of version 3.7 of the lens package,<br>
which provides &quot;Lenses, Folds, and Traversals&quot; for working with<br>
arbitrary data types.<br>
</blockquote>
<br></div>
Do you use types to index the fields of tuples? It&#39;s a good general mechanism to represent the &quot;tupleness&quot; of certain types. I had a quick look and it didn&#39;t seem you were doing this.<br>
<br>
For instance, consider this type:<br>
<br>
 data P = MkP Int Bool Char </blockquote><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">There are classes for Field1..Field9 used for the combinators _1.._9.</blockquote>
<div><br></div><div>If you wanted to make instances of them for your type. You could very well do</div><div><br></div><div><font face="courier new, monospace">instance Field1 P P Int Int where</font></div><div><font face="courier new, monospace">...</font></div>
<div><font face="courier new, monospace">instance Field3 P P Char Char where</font></div><div><font face="courier new, monospace">  _3 f (P a b c) = P a b &lt;$&gt; f c </font></div><div><br></div><div>This lets you use the positional field accessors for monomorphic or polymorphic types, that may or may not allow field types to change.</div>
<div><br></div><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">If one wants to consider the three fields as separate items, one can construct a type that&#39;s an index to them:<br>
 data PInd :: * -&gt; * where<br>   PFirst :: PInd Int<br>   PSecond :: PInd Bool<br>   PThird :: PInd Char<br>It&#39;s then straightforward to construct an isomorphism between P and &quot;forall a. PInd a -&gt; a&quot;. You can also use it to build lenses for the fields, etc.<br>
</blockquote><div><br></div><div>Er, I rather misinterpreted above, (I&#39;ll keep it in this reply just in case it is handy for someone else.)</div></div><div><br></div><div>We do have something rather more limited available, which is that <font face="courier new, monospace">Control.Lens.Representable</font> let you implement corepresentable endofunctors in terms of their polymorphic lenses.</div>
<div><br></div><div>e.g.</div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">import Control.Lens</font></div><div><font face="courier new, monospace"><br></font></div><div>
<font face="courier new, monospace">data V2 a = V2 { __x, __y :: a }</font></div><div><font face="courier new, monospace">makeLenses &#39;&#39;V2</font></div><div><font face="courier new, monospace"><br></font></div><div>
<font face="courier new, monospace">instance Representable V2 where</font></div><div><font face="courier new, monospace">  tabulate f = V2 (f _x) (f _y)</font></div><div><font face="courier new, monospace"><br></font></div>
<div><font face="courier new, monospace">then you can get a number of instances for free</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">instance Monad V2 where</font></div>
<div><font face="courier new, monospace">  return = pureRep</font></div><div><font face="courier new, monospace">  (&gt;&gt;=) = bindRep</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">instance Applicative V2 where</font></div>
<div><font face="courier new, monospace">  pure = pureRep</font></div><div><font face="courier new, monospace">  ap = apRep</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">instance Functor V2 where</font></div>
<div><font face="courier new, monospace">  fmap = fmapRep</font></div><div><font face="courier new, monospace"><br></font></div><div>etc...</div><div><br></div><div>However, the form of representation we use are lenses into the structure instead of  a GADT like index type. This currently limits us to handling functors.</div>
<div><br></div><div>This is used to good effect in the &#39;linear&#39; package, which uses representable functors for all of its vector spaces. This works because, at least classically, all vector spaces are free vector spaces, and those are isomorphic to a function from a basis, so we can use a representable functor with a representation equivalent to that basis as a way to memoize the vector space.</div>
<div><br></div><div>Since it gets comparatively little use relative to the rest of the API and now that the rest of lens has matured around it, it feels somewhat different than the rest of lens, we may want to split this part off into a separate package eventually.</div>
<div><br></div><div>That said, even if we were to add the extra GADT-like index guiding tabulate, it could only do product-like constructions.</div><div><br></div><div>If you use IRC, the #haskell-lens channel on freenode would be a good place to dive into this deeper.</div>
<div><br></div><div>-Edward</div></div>