[Haskell-cafe] Re: Seeking advice on a style question

Udo Stenzel u.stenzel at web.de
Fri Dec 29 20:12:22 EST 2006


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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://www.haskell.org/pipermail/haskell-cafe/attachments/20061230/51d29b7b/attachment.bin


More information about the Haskell-Cafe mailing list