在 elm 的 Record 中使用 Type Bool 时出现奇怪的错误
Strange error using Type Bool in Record in elm
我有以下类型的用户:
type alias User =
{ id : Int
, name : String
, age : Maybe Int
, deleted : Bool
}
用户是我模型中使用的类型:
type alias Model =
{ users : List User
, name : String
, age : String
, message : String
}
当我像这样使用 List.map 遍历 "List User" 时...
Delete id ->
let
newUserList =
List.map
(\user ->
if user.id == id then
{ user | deleted = True }
else
user
)
model.users
in
( { model | users = newUserList }, Cmd.none )
...编译器告诉我:
The 2nd argument to function `map` is causing a mismatch.
List.map
(\user ->
if user.id == id then
{ user | deleted = True }
else
user
)
model.users
Function `map` is expecting the 2nd argument to be:
List { a | id : Int, name : String }
But it is:
List (Bool -> User)
这对我来说很奇怪。
为什么我的地图函数会更改类型用户...?
我不更改它,我只是遍历,映射每个用户,如果我找到了正确的用户,我将根据其 ID 将删除的值更改为 True...
我有点困惑...
有人可以帮忙吗?
亲切的问候 :)
更新:在我看来这不是 List.map 函数的问题,而是类型别名用户声明的问题。
一旦我添加另一个值,它就会中断...
这是它的全部代码。它保持非常简单。
注意:一旦您取消注释用户 属性 "deleted",编译器就会抛出错误
module Main exposing (..)
import Html exposing (Html, text, h1, div, img, input, form, ul, li, i, hr, br)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Html.App as App
import String
import Random
--import Debug
--import Uuid
main : Program Never
main =
App.program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
--MODEL
type alias Model =
{ users : List User
, name : String
, age : String
, message : String
}
type alias User =
{ id : Int
, name : String
, age :
Maybe Int
-- , deleted : Bool
}
init : ( Model, Cmd Msg )
init =
( initModel, Cmd.none )
initModel : Model
initModel =
{ users = []
, name = ""
, age = ""
, message = ""
}
--UPDATE
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
InsertName username ->
( { model | name = username }, Cmd.none )
InsertAge age ->
let
newAge =
case String.toInt age of
Err err ->
""
Ok value ->
toString value
newMessage =
case String.toInt age of
Err err ->
"Age must be a number!"
Ok int ->
""
in
( { model | age = newAge, message = newMessage }, Cmd.none )
InitNewUser ->
( model, Random.generate AddNewUser (Random.int 1 9999) )
AddNewUser randomId ->
if String.isEmpty model.name then
( { model | message = "Please give a name" }, Cmd.none )
else
let
ageAsInt =
case String.toInt model.age of
Err err ->
Nothing
Ok int ->
Just int
newUser =
User randomId model.name ageAsInt
newUserList =
newUser :: model.users
in
( { model | users = newUserList, name = "", age = "" }, Cmd.none )
Delete id ->
let
newUserList =
List.map
(\user ->
if user.id == id then
{ user | name = "--deleted--" }
else
user
)
model.users
in
( { model | users = newUserList }, Cmd.none )
--VIEW
type Msg
= InsertName String
| InsertAge String
| AddNewUser Int
| InitNewUser
| Delete Int
userListView : Model -> Html Msg
userListView model =
let
newList =
List.filter (\user -> (user.name /= "--deleted--")) model.users
in
newList
|> List.sortBy .name
|> List.map userView
|> ul []
userView : User -> Html Msg
userView user =
let
ageAsString =
case user.age of
Just val ->
val |> toString
Nothing ->
"-"
in
li []
[ div [] [ text ("ID: " ++ toString user.id) ]
, div [] [ text ("Name: " ++ user.name) ]
, div [] [ text ("Age: " ++ ageAsString) ]
, input [ type' "button", value "Delete", onClick (Delete user.id) ] []
]
view : Model -> Html Msg
view model =
div [ class "wrapper" ]
[ h1 [] [ text ("We have " ++ toString (List.length model.users) ++ " Users") ]
, Html.form []
[ input [ type' "text", onInput InsertName, placeholder "Name", value model.name ] []
, input [ type' "text", onInput InsertAge, placeholder "Age", value model.age ] []
, input [ type' "button", onClick InitNewUser, value "Add new user" ] []
]
, div [] [ text model.message ]
, userListView model
, hr [] []
, div [] [ text (toString model) ]
]
问题出在 AddNewUser
消息的这一部分:
newUser =
User randomId model.name ageAsInt
当您使用 deleted
属性.
时,缺少 False
作为第四个参数
如果您不包含它,User
函数将 return 一个部分应用的函数,仍然需要 Bool
到 return 一个合适的用户。即使您所有的类型和函数都有适当的注释,编译器似乎也会因此而被抛弃。
导致更好的错误消息的另一种方法是像这样定义 newUser
:
newUser =
{ id = randomId
, name = model.name
, age = ageAsInt
, deleted = False
}
我有以下类型的用户:
type alias User =
{ id : Int
, name : String
, age : Maybe Int
, deleted : Bool
}
用户是我模型中使用的类型:
type alias Model =
{ users : List User
, name : String
, age : String
, message : String
}
当我像这样使用 List.map 遍历 "List User" 时...
Delete id ->
let
newUserList =
List.map
(\user ->
if user.id == id then
{ user | deleted = True }
else
user
)
model.users
in
( { model | users = newUserList }, Cmd.none )
...编译器告诉我:
The 2nd argument to function `map` is causing a mismatch.
List.map
(\user ->
if user.id == id then
{ user | deleted = True }
else
user
)
model.users
Function `map` is expecting the 2nd argument to be:
List { a | id : Int, name : String }
But it is:
List (Bool -> User)
这对我来说很奇怪。 为什么我的地图函数会更改类型用户...? 我不更改它,我只是遍历,映射每个用户,如果我找到了正确的用户,我将根据其 ID 将删除的值更改为 True...
我有点困惑... 有人可以帮忙吗?
亲切的问候 :)
更新:在我看来这不是 List.map 函数的问题,而是类型别名用户声明的问题。 一旦我添加另一个值,它就会中断...
这是它的全部代码。它保持非常简单。 注意:一旦您取消注释用户 属性 "deleted",编译器就会抛出错误
module Main exposing (..)
import Html exposing (Html, text, h1, div, img, input, form, ul, li, i, hr, br)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Html.App as App
import String
import Random
--import Debug
--import Uuid
main : Program Never
main =
App.program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
--MODEL
type alias Model =
{ users : List User
, name : String
, age : String
, message : String
}
type alias User =
{ id : Int
, name : String
, age :
Maybe Int
-- , deleted : Bool
}
init : ( Model, Cmd Msg )
init =
( initModel, Cmd.none )
initModel : Model
initModel =
{ users = []
, name = ""
, age = ""
, message = ""
}
--UPDATE
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
InsertName username ->
( { model | name = username }, Cmd.none )
InsertAge age ->
let
newAge =
case String.toInt age of
Err err ->
""
Ok value ->
toString value
newMessage =
case String.toInt age of
Err err ->
"Age must be a number!"
Ok int ->
""
in
( { model | age = newAge, message = newMessage }, Cmd.none )
InitNewUser ->
( model, Random.generate AddNewUser (Random.int 1 9999) )
AddNewUser randomId ->
if String.isEmpty model.name then
( { model | message = "Please give a name" }, Cmd.none )
else
let
ageAsInt =
case String.toInt model.age of
Err err ->
Nothing
Ok int ->
Just int
newUser =
User randomId model.name ageAsInt
newUserList =
newUser :: model.users
in
( { model | users = newUserList, name = "", age = "" }, Cmd.none )
Delete id ->
let
newUserList =
List.map
(\user ->
if user.id == id then
{ user | name = "--deleted--" }
else
user
)
model.users
in
( { model | users = newUserList }, Cmd.none )
--VIEW
type Msg
= InsertName String
| InsertAge String
| AddNewUser Int
| InitNewUser
| Delete Int
userListView : Model -> Html Msg
userListView model =
let
newList =
List.filter (\user -> (user.name /= "--deleted--")) model.users
in
newList
|> List.sortBy .name
|> List.map userView
|> ul []
userView : User -> Html Msg
userView user =
let
ageAsString =
case user.age of
Just val ->
val |> toString
Nothing ->
"-"
in
li []
[ div [] [ text ("ID: " ++ toString user.id) ]
, div [] [ text ("Name: " ++ user.name) ]
, div [] [ text ("Age: " ++ ageAsString) ]
, input [ type' "button", value "Delete", onClick (Delete user.id) ] []
]
view : Model -> Html Msg
view model =
div [ class "wrapper" ]
[ h1 [] [ text ("We have " ++ toString (List.length model.users) ++ " Users") ]
, Html.form []
[ input [ type' "text", onInput InsertName, placeholder "Name", value model.name ] []
, input [ type' "text", onInput InsertAge, placeholder "Age", value model.age ] []
, input [ type' "button", onClick InitNewUser, value "Add new user" ] []
]
, div [] [ text model.message ]
, userListView model
, hr [] []
, div [] [ text (toString model) ]
]
问题出在 AddNewUser
消息的这一部分:
newUser =
User randomId model.name ageAsInt
当您使用 deleted
属性.
False
作为第四个参数
如果您不包含它,User
函数将 return 一个部分应用的函数,仍然需要 Bool
到 return 一个合适的用户。即使您所有的类型和函数都有适当的注释,编译器似乎也会因此而被抛弃。
导致更好的错误消息的另一种方法是像这样定义 newUser
:
newUser =
{ id = randomId
, name = model.name
, age = ageAsInt
, deleted = False
}