Hi Joerg. I must admit that I do not fully understand the big picture, i.e., why you want to do what you are trying to do. It might be possible to recommend a better solution using a library such as guarded-rewriting on Hackage then. I've tried to look up the SO question (http://stackoverflow.com/questions/13436366/manipulating-arbitrary-tuples), but it doesn't really make me understand your goal completely either.
In the code you provide, which is taken from one of the answers, the Bool parameter indeed ensures that the first element of a chain of products is treated in a different way from the rest. The key to this behaviour is the line > rewrite x (a :*: b) = rewrite x a :*: rewrite True b Here, assuming rewrite is first called with False, we ensure that the very first component of the nested product will be called with False, all others with True. Hence all but the first component will end up being rewritten. If you'd like to rewrite all but the last, you could achieve this just by writing > rewrite x (a :*: b) = rewrite True a :*: rewrite x b instead. If you want to keep the first and the last component, you need to propagate more information than a simple Bool. One option is to create a special-purpose datatype: > data What = Both | First | Last | None > deriving Eq The type of rewrite becomes: > rewrite :: What -> f a -> (Rewrite f) a The idea is that the What argument is initialized to Both, and in every product case, we split the current value of What to keep track if we are in the leftmost part of the product (First), the rightmost part of the product (Last), or elsewhere (None). For this, we define > splitWhat :: What -> (What, What) > splitWhat Both = (First, Last) > splitWhat First = (First, None) > splitWhat Last = (None, Last) > splitWhat None = (None, None) The product case of rewrite is now: > rewrite x (a :*: b) = rewrite y a :*: rewrite z b > where (y, z) = splitWhat x We also need to slightly modify the K1 case of rewrite. We now want to perform the rewrite if What is anything but None: > rewrite w (K1 x) | w /= None, Just val <- cast x = K1 val > rewrite _ _ = K1 "NIL" Does this help you? (I'm attaching the full code.) Cheers, Andres -- Andres Löh, Haskell Consultant Well-Typed LLP, http://www.well-typed.com
GRewrite.hs
Description: Binary data
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe