applyFlipped, ‘#’¶
Type signature:
applyFlipped :: ∀ a b. a -> (a -> b) -> b
Compare with apply
:
apply :: ∀ a b. (a -> b) -> a -> b
applyFlipped :: ∀ a b. a -> (a -> b) -> b
Given the type signatures, it is clear that applyFlipped
is really the flipped version of apply
.
Under the light of that piece of insight, one way to implement applyFlipped
is in terms of apply
.
applyFlipped :: ∀ a b. a -> (a -> b) -> b
applyFlipped = flip apply
By writing applyFlipped
in terms of apply
, we can make it point-free.
Or we can write it “manually”, without reusing apply
:
applyFlipped :: ∀ a b. a -> (a -> b) -> b
applyFlipped x f = f x
This is how we would use it.
Let’s compare with apply
:
> apply show 1
"1"
> applyFlipped 1 show
"1"
We apply the show
function to the value 1, or, using the flipped version, we first provide the value, then the function.
apply f to x or apply x to f
We have function application, not value application. By definition, it is correct to say that “we apply a function to a value”, and not that “we apply a value to a function”. Still, it is becoming more common to say or write both interchangeably. See my question about this on the PureScript Discord server.
> import Prelude (show, identity)
> apply show 1
"1"
> applyFlipped 1 show
"1"
> apply show (identity 1)
"1"
> applyFlipped (identity 1) show
"1"
Using ‘#’ (number/hash/pound symbol) infixl applyFlipped operator¶
Whatever implementation we may chose for applyFlipped
, we can write it as an infixl operator:
applyFlipped :: ∀ a b. a -> (a -> b) -> b
applyFlipped = flip apply
infixl 0 applyFlipped as #
Here too, as in apply
, we need the precedence to be 0 (the lowest possible) so we first evaluate things on the left (infixl) and only then evalutate things on the right.
And some examples of its use (comparing with $
/apply
):
> import Effect.Console (log)
> import Prelude (identity, show)
> log $ show $ identity 1
1
> identity 1 # show # log
1
The #
operator makes it more readable (at last to some people).
In the book Functional Programming Made Easier, Charles Scalfani shows an example comparing $
and #
:
f x $ step3 $ step2 $ step1 x
f x $ step1 # step2 # step3 x
Indeed, #
(applyFlipped
) does help with readability and reasoning about code in some situations.
If you have ever used Ramda, apply
is like compose()
, while applyFlipped
is like pipe()
.