1
votes

I'm trying to make a very simple application in F#. I want just to make a tiny button with the click event, which will call the MessageBox.Show() method.

open System
open System.Windows.Forms

module FSI =
    [<System.Runtime.InteropServices.DllImport("user32.dll")>]
    extern bool ShowWindow(nativeint hWnd, int flags)
    let HideConsole() = 
        let proc = System.Diagnostics.Process.GetCurrentProcess()
        ShowWindow(proc.MainWindowHandle, 0)

FSI.HideConsole()

let form1 = new Form()
form1.Text <- "App"

let Test() = ( MessageBox.Show("Clicked.") )

let button1 = new Button( Text = "Click Me" )
button1.Click.AddHandler(fun _ _ -> Test())

form1.Controls.Add(button1)    

[<STAThread>]
do
   Application.Run(form1)

The errors occurred for the:

  • FSI.HideConsole() // warning
  • button1.Click.AddHandler(fun _ _ -> Test()) // compiler error

And they are similar.

For the 1-st:

  • Warning This expression should have type 'unit', but has type 'bool'. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name.

For the 2-nd:

  • This expression was expected to have type unit but here has type DialogResult
1

1 Answers

1
votes

F# functions implicitly return the result of their last expression, so currently your function Test() returns the result of MessageBox.Show(string). To create a function that returns void/unit, you can use the ignore operator.

let Test() = ignore (MessageBox.Show("Clicked."))

It's a bit cumbersome to have to do the extra parenthesis wrapping, so typically one uses the pipeforward (|>) operator, which doesn't require that:-

let Test() = MessageBox.Show("Clicked.") |> ignore

This can also be applied to your call of HideConsole. The compiler uses the warning to inform you that the return value of HideConsole is not used.