I was bored one day and wanted to exercise my brain, so I decided to do the 99 Haskell Problems but restricted myself to doing them in point-free style. A problem that seems to crop up a lot when I'm doing things in point-free style is this: How do you apply multiple functions to the same value while keeping each result as an independent entity? Using pointed notation:
foobar x = [id x, reverse x]
And what I've come up with so far in point-free notation:
foobar' = `map` [id, reverse] ($ x)
I can't seem to get that x
off the end of there.
You will be interested in the
Applicative
instance of the reader monad:Using it you can easily distribute an argument:
Here
sin
andcos
are functions, which both receive the value 3. The individual results are then combined using(+)
. You can further combine this with theCategory
instance of(->)
, but of cource specialized versions of(.)
andid
are already defined in thePrelude
.Background: The
Applicative
instance for(e ->)
really represents the SKI calculus, where(<*>)
is the S combinator andpure
is the K combinator. S is precisely used to distribute an argument to two functions:It takes a function application (f g) and makes both dependent on the value x ((f x) (g x)).
Use sequence:
There are a few basic idiomatic combinators which pop up repeatedly, and are reimplemented with various higher concepts and libraries, but which are essentially very simple. Names may vary, and some are implementable in terms of others:
etc. Of course
uncurry f (x,y) == f x y
gets used a lot with these, too.&&&
and***
are defined inControl.Arrow
, as well asfirst
andsecond
. Thenprod (f,id) == first f
,prod(id,g) == second g
etc. etc.So your
foobar
becomesFor the last one you need to also import
Control.Monad
andControl.Monad.Instances
. See also this question.late edit: also, using
Control.Applicative
as hinted in answer by ertes,Others have already posted how you can do this using the
Reader
monad, but that's not the only way. It turns out that your second function is pretty close. I think you meant to postSince the
x
is already near a rightmost position, you're almost there. First, transform the section($ x)
into a function, because it's a bit easier to work with:Next remove the
x
from the lambda body by bringing a new variable into scope, and applying the function tox
Rewrite this application as a function composition, and then you can eta reduce:
Finally, notice that we can replace the lambda with a function
and you have a point-free form.