Почему компилятор сообщает мне "Неправильное соответствие типа для сообщения приложения", когда они одного типа
Итак, я борюсь с компилятором из-за ошибки типа.
Этот код работал пару дней назад.
Введите misMatch для сообщения уровня приложения
Фрагменты App.fs
module App =
type Msg =
| ConnectionPageMsg of ConnectionPage.Msg
| CodeGenPageMsg of CodeGenPage.Msg
//...
let update (msg : Msg) (model : Model) =
match msg with
| ConnectionPageMsg msg ->
let m, cmd = ConnectionPage.update msg model.ConnectionPageModel
{ model with ConnectionPageModel = m }, cmd
| CodeGenPageMsg msg ->
let m, cmd = CodeGenPage.update msg model.CodeGenPageModel
{ model with CodeGenPageModel = m }, cmd
//...
let runner =
Program.mkProgram init update view
|> Program.withConsoleTrace
|> XamarinFormsProgram.run app
Я добавил явные псевдонимы и исходную ошибку:
Type mismatch. Expecting a
'App.Msg -> App.Model -> App.Model * Cmd<App.Msg>'
but given a
'App.Msg -> App.Model -> App.Model * Cmd<Msg>'
The type 'App.Msg' does not match the type 'Msg'
Стали такими:
App.fs(50,50): Error FS0001: The type 'PocoGen.Page.ConnectionPage.Msg' does not match the type 'PocoGen.Page.CodeGenPage.Msg' (FS0001) (PocoGen)
App.fs(32,32): Error FS0001: Type mismatch.
Expecting a 'App.Msg -> App.Model -> App.Model * Cmd<App.Msg>'
but given a 'App.Msg -> App.Model -> App.Model * Cmd<Msg>'
The type 'App.Msg' does not match the type 'Msg' (FS0001) (PocoGen)
Прочие замечания
Прямо перед тем, как эти ошибки начали появляться, я работал над преобразованием блокирующего синхронного вызова в асинхронную команду в ConnectionTestPage и удалил вызывающий код для cmd, надеясь, что это исправит. (Это не так)
Сообщения ConnectionPage.fs
type Msg =
| UpdateConnectionStringValue of string
| UpdateConnectionStringName of string
| TestConnection
| TestConnectionComplete of Model
| SaveConnectionString of ConnectionStringItem
| UpdateOutput of string
Обновление ConnectionPage.fs
let update (msg : Msg) (m : Model) : Model * Cmd<Msg> =
match msg with
| UpdateConnectionStringValue conStringVal ->
{ m with
ConnectionString =
{ Id = m.ConnectionString.Id
Name = m.ConnectionString.Name
Value = conStringVal }
CurrentFormState =
match hasRequredSaveFields m.ConnectionString with
| false -> MissingConnStrValue
| _ -> Valid }, Cmd.none
| UpdateConnectionStringName conStringName ->
{ m with
ConnectionString =
{ Id = m.ConnectionString.Id
Name = conStringName
Value = m.ConnectionString.Value }
CurrentFormState =
match hasRequredSaveFields m.ConnectionString with
| false -> MissingConnStrValue
| _ -> Valid }, Cmd.none
| UpdateOutput output -> { m with Output = output }, Cmd.none
| TestConnection -> m, Cmd.none
| TestConnectionComplete testResult -> { m with Output = testResult.Output + "\r\n" }, Cmd.none
| SaveConnectionString(_) -> saveConnection m, Cmd.none
Я играл с версией Fsharp (потому что, кстати, я обновился до 4.7.2
немного до получения этой ошибки)
Полное репо:
https://github.com/musicm122/PocoGen_Fsharp/tree/master/PocoGen
1 ответ
Две ветви match
внутри App.update
бывают разные типы. Первая ветка имеет типApp.Model * Cmd<ConnectionPage.Msg>
а вторая страница имеет тип App.Model * Cmd<CodeGenPage.Msg>
.
Обычно вы не можете этого сделать. Это, например, не компилируется:
let x =
match y with
| true -> 42
| false -> "foo"
Какой тип x
Вот? Этоint
или это string
? Не вычисляет. Аmatch
выражение должно иметь все ветви одного типа.
Конвертировать Cmd<ConnectionPage.Msg>
в Cmd<App.Msg>
(заключив сообщение в ConnectionPageMsg
) вы можете использовать Cmd.map
:
let update (msg : Msg) (model : Model) =
match msg with
| ConnectionPageMsg msg ->
let m, cmd = ConnectionPage.update msg model.ConnectionPageModel
{ model with ConnectionPageModel = m }, Cmd.map ConnectionPageMsg cmd
| CodeGenPageMsg msg ->
let m, cmd = CodeGenPage.update msg model.CodeGenPageModel
{ model with CodeGenPageModel = m }, Cmd.map CodeGenPageMsg cmd