Why does my version of the Elmish.WPF Sample NewWindow (XAML code and F# Core) emit the error ...
- The type 'unit -> 'a' is not compatible with the type 'Window'.
The same line emits the warning...
- This construct causes code to be less generic than indicated by its type annotations. The type variable implied by the use of a '#', '_' or other type annotation at or near <line reference to createWindow_Window2 in the let bindings = statement">
Why am I getting this error and warning?
What I am doing is merging the Elmish.WPF Samples SingleCounter (XAML code and F# Core) and NewWindow (XAML code and F# Core) to have the Model, bindings(), and Msg parts in Program.fs instead of App.fs (as it was in the NewWindow sample).
My goal is to make a SimpleCounter able to open a NewWindow.
The XAML code passes Func<Window2> into the F# code here...
let main mainWindow (createWindow2: Func<#Window>)
...I define bindings as...
let bindings = Platform.bindings createWindow_Window2
I am down to the one compiler error I mentioned above (and that also appears in line beginning "let bindings = ..." below)...
let main mainWindow (createWindow_Window2: Func<#Window>) =
let logger =
LoggerConfiguration()
.MinimumLevel.Override("Elmish.WPF.Update", Events.LogEventLevel.Verbose)
.MinimumLevel.Override("Elmish.WPF.Bindings", Events.LogEventLevel.Verbose)
.MinimumLevel.Override("Elmish.WPF.Performance", Events.LogEventLevel.Verbose)
.WriteTo.Console()
.CreateLogger()
let createWindow_Window2 =
let window = createWindow_Window2.Invoke()
window.Owner <- mainWindow
window
let bindings = Platform.bindings createWindow_Window2
WpfProgram.mkProgramWithCmdMsg (fun _ -> m_init, []) update bindings toCmd
|> WpfProgram.withLogger (new SerilogLoggerFactory(logger))
|> WpfProgram.startElmishLoop mainWindow
The top of Program.bindings is defined as ...
let bindings (createWindow_Window2: unit -> #Window) () : Binding<Model, Msg> list = [
"Window_Window2_Show|> Binding.cmd Window_AboutProduct_Show
"Window_Window2" |> Binding.subModelWin(
Window_Window2.get >> WindowState.ofOption,
snd,
Window_Window2ct.mapInOutMsg,
Window_Window2_Module.Window_Window2.bindings,
createWindow_Window2,
isModal = true)
...bindings continue but are not relevant to this question...
... and reports no errors!
The compiler seems to think Platform.bindings is expecting unit -> `a when createWindow_Window2 is correctly typed as unit -> #Window.
You can see the call into Program.fs:main is correctly called from App.xaml.cs with a lambda function returning a Window2 as follows...
private void StartElmish(object sender, EventArgs e)
{
this.Activated -= StartElmish;
Program.main(MainWindow, () => new Window2());
}
So my question is why am I getting this mismatch type error when it seems I am passing the correct types?
Thank you!
A big thank you to: Brian Berns, Bent Tranberg, and Tomas Petricek for helping me!
The answer to my problem was astonishingly simple to an expert but to a relative novice only yielded after meticulous comparison with the working Elmish.WPF code for NewWindow.
For easy comparison I have pushed up to rfreytag/Elmish.WPF a version of the NewWindow (XAML code and F# Core) sample that compiles and runs (REMEMBER to build the NewWindow sample).
This version of NewWindow (XAML code and F# Core) when compiled shows the error and warning I reported above …
...and the warning...
To see the precise fix you can compare the working and breaking branches on my copy of Elmish.WPF. Which is that I had forgotten the
()following the definition oflet createWindow_Window2 =...... returns the function
() -> Windowwhile the correct ...... returns the needed
Window.A newbie looks at
unit → ‘aand doesn’t immediately recognize it as a function. And of course, functions are not C#Windowobjects.Did not help me that the error message doesn’t follow the F# form of...
...which has become familiar from working with the F# compiler.
Not sure why this message diverged from that pattern. Maybe someone can explain that?
The warning is alerting to the less-specific
#Window(see # ‘flexible type’ definition) possibly clashing at run-time with theunit → ‘afunction.As usual, learning a new framework means learning the compiler and linker messages.