&gt;  takeC :: Int -&gt; Compoz a b -&gt; (exists c. Compoz a c)<br>
 &gt;  dropC :: Int -&gt; Compoz a b -&gt; (exists c. Compoz c b)<br><br>What does &#39;exists&#39; means? To create a rank-2 type can&#39;t you use:<br><br>takeC :: Int -&gt; Compoz a b -&gt; (forall c. Compoz a c)<br><br>

??<br><br><div class="gmail_quote">
2011/2/28 Heinrich Apfelmus <span dir="ltr">&lt;<a href="mailto:apfelmus@quantentunnel.de" target="_blank">apfelmus@quantentunnel.de</a>&gt;</span><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">


Yitzchak Gale 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><div></div><div>
You have written a large software system in Haskell. Wishing to<br>
play to Haskell&#39;s strength, you have structured your system<br>
as a series of composable layers. So you have data types<br>
<br>
Layer1, Layer2, ...<br>
<br>
and functions<br>
<br>
layer2 :: Layer1 -&gt; Layer2<br>
layer3 :: Layer2 -&gt; Layer3<br>
....<br>
<br>
etc.<br>
<br>
Of course you&#39;ll want to be able to run any range<br>
of the layers separately, at least for testing and debugging<br>
purposes if not for the functionality itself.<br>
<br>
So your UI module (command line or whatever) that launches<br>
your application provides a data type<br>
<br>
data Layers = Layers Int Int<br>
<br>
that indicates which layers to run, and functions<br>
<br>
deserialize1 :: L.ByteString -&gt; Layer1<br>
deserialize2 :: L.ByteString -&gt; Layer2<br>
....<br>
<br>
serialize1 :: Layer1 -&gt; L.ByteString<br>
serialize2 :: Layer2 -&gt; L.ByteString<br>
....<br>
<br>
etc.<br>
<br>
Now you need a function<br>
<br>
runLayers :: Layers -&gt; L.ByteString -&gt; L.ByteString<br>
<br>
so that the effect is for example<br>
<br>
runLayers (Layers 4 6) = serialize6 . layer6 . layer5 . deserialize4<br>
<br></div></div>
[..]<div><br>
<br>
What is the best way to write runLayers? Feel free to change<br>
the details of the above design, as long as it meets the<br>
functionality requirements expressed.<br>
</div></blockquote>
<br>
Solution: compose all the functions, but do not use the standard function composition (.) to do that. Instead, make a new data type with composition as constructor. This way, you can inspect the composition afterwards and run only parts of it.<br>



<br>
Solution, put differently: Make a type-safe list of the whole chain of functions. Then, the  runLayers  function throws away everything outside the range and composes what is left.<br>
<br>
Here a rough sketch of what I have in mind:<br>
<br>
   data Compoz a b where<br>
       Id   :: Compoz a a<br>
       Cons :: (Serialize a,b,c) =&gt; (b -&gt; c) -&gt; Compoz a b -&gt; Compoz a c<br>
<br>
   -- this value needs to be written out<br>
   chain = layer20 `Cons` layer 19 ...<br>
<br>
   runLayers (Layer a b) =<br>
       deserialize . (run . takeC (b-a) . dropC a $ chain) . serialize<br>
<br>
   takeC :: Int -&gt; Compoz a b -&gt; (exists c. Compoz a c)<br>
   dropC :: Int -&gt; Compoz a b -&gt; (exists c. Compoz c b)<br>
<br>
   run :: Compoz a b -&gt; (a -&gt; b)<br>
<br>
Of course, you will have to wrestle with the existential types for takeC  and  dropC  a bit, but that shouldn&#39;t be much of a problem. For instance, you can fuse these functions into  runLayers  and hide the existential types somewhere in the recursion.<br>



<br>
<br>
Regards,<br>
Heinrich Apfelmus<br><font color="#888888">
<br>
--<br>
<a href="http://apfelmus.nfshost.com" target="_blank">http://apfelmus.nfshost.com</a></font><div><div></div><div><br>
<br>
<br>
_______________________________________________<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>