Hi Max,<br><br><div class="gmail_quote"><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
I&#39;ve come into trouble defining function `gmap` which will work on these<br>
data types:<br>
<br>
&gt; data Row = Row<br>
&gt;      (E Name)<br>
&gt;      (E Salary)<br>
&gt;      (E Department)<br>
<br>
&gt; type E a = Either (Maybe RowIndex) (Maybe a)<br>
<br>
&gt; type RowIndex = Int<br>
<br>
`RowIndex`, `Name`, `Salary`, `Department` have kind *<br>
<br>
pseudocode:<br>
<br>
&gt; gmap :: (E a -&gt; E a) -&gt; Row -&gt; Row<br>
<br>
</blockquote><div><br>[...]<br> <br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">So, generic programming folks, is it even possible to define such<br>


function?  I don&#39;t really care about using GHC extensions, I don&#39;t care<br>
about code being portable, I just want to remove boilerplate and prevent<br>
introducing bugs.<br>
</blockquote><div><br>I&#39;m not sure the problem you&#39;re running into is strictly a generic programming (GP) one. Typically, GP takes code that is often written and generalizes it, so that it doesn&#39;t have to be written for multiple datatypes.<br>

<br>For your problem, I think the first issue is figuring out how to write the non-generic function. I don&#39;t know if this is exactly what you want, but you can write a version of gmap using GADTs and rank-2 types. I&#39;ve simplified some types, but it should be easily transferable to your code. For example, change the String, Float, etc. to your Salary, Department, whatever.<br>

<br>---<br><br>{-# LANGUAGE GADTs #-}<br>{-# LANGUAGE Rank2Types #-}<br><br>module Main where<br><br>data T a where<br>  String  :: T String<br>  Float   :: T Float<br>  Integer :: T Integer<br><br>data Row = Row (Maybe String) (Maybe Float) (Maybe Integer)<br>

  deriving Show<br><br>f :: T a -&gt; Maybe a -&gt; Maybe a<br>f String (Just &quot;a&quot;) = Just &quot;z&quot;<br>f _      x = x<br><br>gmap :: (forall a . T a -&gt; Maybe a -&gt; Maybe a) -&gt; Row -&gt; Row<br>gmap f (Row x y z) = Row (f String x) (f Float y) (f Integer z)<br>

<br>main = do<br>  print $ gmap f $ Row Nothing (Just 5.4) (Just 3) -- ==&gt; Row Nothing (Just 5.4) (Just 3)<br>  print $ gmap f $ Row (Just &quot;a&quot;) Nothing Nothing -- ==&gt; Row (Just &quot;z&quot;) Nothing Nothing<br>

<br>---<br><br>If this is what you&#39;re looking for, then I think it might be possible to do this more generally, though I haven&#39;t looked into it.<br><br>Regards,<br>Sean<br></div></div>