My previous answer explains what Value Restriction is and why it happens. But now your next question is: ok, so what do I do about it?
As the error message itself suggests, there are two possible ways: (1) give it explicit arguments or (2) if you don't want it to be generic, add a type annotation.
1. Explicit arguments
let flippedPipe x = flip (|>) x
Even though logically this is the same as let flippedPipe = flip (|>)
, syntactically this is now a function, not a value. And syntax is what matters for the Value Restriction.
2. A type annotation
let flippedPipe : (int -> int) -> int -> int = flip (|>)
This works because the function is no longer generic, so the Value Restriction does not apply. This is a desirable option in many circumstances, but judging by the kinds of functions you're working with here, I would assume this is not what you wanted in this case.
3. Explicit type parameters
The error message doesn't mention this, and in fairness, it can be considered a variation of option (2). The idea is that you can give your function explicit type parameters like this:
let flippedPipe<'a, 'b> = flip (|>)
This makes the Value Restriction go away, because, even though it still technically applies, the fact that you added the type parameters presumably shows that you know what you're doing, so the compiler shuts up.
However, though this appears to work at first glance, it does so in the wrong way. If you look at the inferred type of this function, you'll see:
val flippedPipe : (obj -> obj) -> obj -> obj
This happens because, even though you added type parameters, you didn't specify exactly where they go. They may not be used at all (aka "phantom types") for all the compiler knows.
So to make it work properly, this should be the definition:
let flippedPipe<'a, 'b> : ('a -> 'b) -> 'a -> 'b = flip (|>)