2

I have a side-effecting function, f : int -> string -> unit which I am calling using f 1 "hi".

To make sure I get an error in the call site if the function is changed to need more arguments, I call the function using () = f 1 "hi" |> ignore. This would ensure a type error if the function is partially applied and no side-effects would be performed.

Is there a more elegant way of avoiding accidental partial application?

Janus Troelsen
  • 20,267
  • 14
  • 135
  • 196

3 Answers3

4

Add a "guard" parameter at the very end:

let f a b c () = ...

And pass it at call site:

f 42 "foo" 3.14 ()

If you add another parameter, its type won't match unit (unless you're adding a unit parameter, but why would you do that?), and the compiler will complain at call site.

An extra unit parameter is a common way of denoting a function that is side-effect-only.

For pure functions, on the other hand, this trick is not needed, since you would be interested in their return value, and accidental partial application would change the type of that, cause the compiler to complain.

Fyodor Soikin
  • 78,590
  • 9
  • 125
  • 172
3

The warning you get from the compiler is FS0193 : "This expression is a function value, i.e. is missing arguments."

In Visual Studio, in the project properties, in Treat warnings as errors, Specific warnings, add 0193. Use semicolon as separator if needed.

I don't see how it can get more elegant than this. The source will look just as expected without any added mystery, but compilation fails if you modify the function without also adjusting the call site. In fact I don't understand why this warning isn't an error by default.

If you don't use VS, then edit settings manually in the project file, as explained here.

Bent Tranberg
  • 3,445
  • 26
  • 35
1

I would add just type annotation

f 1 "hi" : unit

That's it.

Bartek Kobyłecki
  • 2,365
  • 14
  • 24