[Haskell-cafe] A practical Haskell puzzle

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 Typically there could be 20 or 30 layers, so writing out each case could result in hundred of boilerplate definitions for runLayers. Scripting the generation of all that boilerplate, e.g. using TH, doesn't seem very attractive either. On the other hand, it seems silly to have to use super-advanced type olegery for such a trivially simple yet centrally important component of the system. 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. Regards, Yitz