Search code examples
f#partial-applicationinfix-operator

Not getting the same result from a partial application as with an infix opperatior "(%) x y <> x % y -> wtf"


I've just been doing some validation on value to see it is a product of three. Great use the modulus function. I want to pipe to it. Great use a partial application. But apparently not.

This is an example from my fsi in vs code.

> 27 % 3
-
- ;;
val it : int = 0

> (%) 3 27
- ;;
val it : int = 3

I really didn't expect to get a different result from an infix vs a partial.

Here is the operation in a pipe for context:

...
|> Seq.length // 27
|> (%) 3 // 3

Solution

  • Partial application of an infix doesn't work as I expected. The statement in my qustion is incorrect and this isn't a bug. It might be a fairly common missunderstanding for beginers so its worth a good explaination.

    (%) x y = x % y
    

    Therefore

     (%) 27 3
     = 27 % 3
     = 0
    

    The confusion comes when piping in the final value, the y. you should not expect

    y
    |> (%) x
    

    to result in

     y % x
    

    but rather

    x % y
    

    This is a little bit confusing particularly if you have used an infix operator, which does treats inputs symetrically (e.g +,=,<>,*), without questioning too deeply. You must take care that order of values supplied to an infix opperator are correct, even if it looks right at first inspection.

    The clearest and most verbose way to handle an infix opperator, which accepts values in the opposite order to which you wish to supply them, is to just write out a lambda. However, there is also the option to back pipe '<|'.

    Here is a snippet of code which was causing me a bug due to my misuse of the partially applied infix.

    ...
    |> Seq.length // 27
    |> (%) 3 // 3 % 27 = 3
    

    It could be written with a backpipe to perform as expected

    ...
    |> Seq.length // 27
    |> (%) <|3 // 27 % 3 = 0
    

    or more clearly with a lambda

    ...
    |> Seq.length // 27
    |> (fun x -> x % 3 // 27 % 3 = 0