
Steve Schafer wrote:
Here's the essence of the problem. If I have this:
process1 x y = let u = foo x y; v = bar u; w = baz v in w
I can easily rewrite it in point-free style:
process1 = baz . bar . foo
That should have been process1 = (.) (baz . bar) . foo or something similar. You might want to define suitable combinators if you have this pattern more often: infix 8 .< (.<) = (.) . (.) process1 = baz . bar .< foo
But if I have this:
process2 x y = let u = foo x y; v = bar u; w = baz v u in w
then I can't avoid naming and using an intermediate variable.
Turns out you can. process2 = \x y -> (\u -> baz (bar u) u) (foo x y) = \x y -> (\u -> (baz . bar) u u) (foo x y) = \x y -> liftM2 (baz . bar) (foo x y) = liftM2 (baz . bar) .< foo In fact, you never need named values. Read "How to Mock a Mockingbird" by Richard Bird (if memory serves) or the documentation for the Unlamda (esoteric) programming language to find out how or let Lambdabot do the transformation to pointless style for you. You don't need to go fully points free in every case. In your original example, only one intermediate (y01) was actually used more than once and deserves naming. Everything else can be composed with the help of 'uncurry'. 'liftM2' is also surprisingly useful, but it's use at the type constructor (r ->) as in the last example probably deserves a name of its own.
The u in process2 is of no more value to me (pardon the pun) as the one in process1, but I am forced to use it simply because the data flow is no longer strictly linear.
Instead you could define intermediate functions by composing functions with the help of a few combinators. I guess, the construction (liftM2 (baz . bar)) could have a very meaningful name. Some combinators might also vanish if you reorder and/or tuple some of the arguments to existing functions.
The reason I brought up monads as a possible means of managing this problem is that the State, Reader and Writer monads already handle certain specific "shapes" of nonlinear data flow
Uhm... that could be said of Reader, but is no good description of the others. If you like, you could plug your y01 into a Reader Monad, but I don't think it simplifies anything. Sometimes naming values is simply the right thing to do. -Udo -- Even if you're on the right track, you'll get run over if you just sit there. -- Will Rogers