> takeC :: Int -> Compoz a b -> (exists c. Compoz a c) > dropC :: Int -> Compoz a b -> (exists c. Compoz c b)
What does 'exists' means? To create a rank-2 type can't you use: takeC :: Int -> Compoz a b -> (forall c. Compoz a c) ?? 2011/2/28 Heinrich Apfelmus <[email protected]> > Yitzchak Gale wrote: > >> You have written a large software system in Haskell. Wishing to >> play to Haskell's strength, you have structured your system >> as a series of composable layers. So you have data types >> >> Layer1, Layer2, ... >> >> and functions >> >> layer2 :: Layer1 -> Layer2 >> layer3 :: Layer2 -> Layer3 >> .... >> >> etc. >> >> Of course you'll want to be able to run any range >> of the layers separately, at least for testing and debugging >> purposes if not for the functionality itself. >> >> So your UI module (command line or whatever) that launches >> your application provides a data type >> >> data Layers = Layers Int Int >> >> that indicates which layers to run, and functions >> >> deserialize1 :: L.ByteString -> Layer1 >> deserialize2 :: L.ByteString -> Layer2 >> .... >> >> serialize1 :: Layer1 -> L.ByteString >> serialize2 :: Layer2 -> L.ByteString >> .... >> >> etc. >> >> Now you need a function >> >> runLayers :: Layers -> L.ByteString -> L.ByteString >> >> so that the effect is for example >> >> runLayers (Layers 4 6) = serialize6 . layer6 . layer5 . deserialize4 >> >> [..] >> >> >> What is the best way to write runLayers? Feel free to change >> the details of the above design, as long as it meets the >> functionality requirements expressed. >> > > 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. > > 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. > > Here a rough sketch of what I have in mind: > > data Compoz a b where > Id :: Compoz a a > Cons :: (Serialize a,b,c) => (b -> c) -> Compoz a b -> Compoz a c > > -- this value needs to be written out > chain = layer20 `Cons` layer 19 ... > > runLayers (Layer a b) = > deserialize . (run . takeC (b-a) . dropC a $ chain) . serialize > > takeC :: Int -> Compoz a b -> (exists c. Compoz a c) > dropC :: Int -> Compoz a b -> (exists c. Compoz c b) > > run :: Compoz a b -> (a -> b) > > Of course, you will have to wrestle with the existential types for takeC > and dropC a bit, but that shouldn't be much of a problem. For instance, > you can fuse these functions into runLayers and hide the existential types > somewhere in the recursion. > > > Regards, > Heinrich Apfelmus > > -- > http://apfelmus.nfshost.com > > > > _______________________________________________ > Haskell-Cafe mailing list > [email protected] > http://www.haskell.org/mailman/listinfo/haskell-cafe >
_______________________________________________ Haskell-Cafe mailing list [email protected] http://www.haskell.org/mailman/listinfo/haskell-cafe
