在elm中使用记录中的类型Bool的奇怪错误

时间:2016-11-07 20:51:32

标签: 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函数的问题,而是类别别名User声明的问题。 一旦我添加另一个值,这就会破坏......

以下是它的完整代码。它保持非常简单。 注意:只要取消注释Users属性“已删除”,编译器就会抛出错误

    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) ]
            ]

1 个答案:

答案 0 :(得分:1)

问题是AddNewUser消息的这一部分:

newUser =
    User randomId model.name ageAsInt

当您使用False属性时,它缺少deleted作为第四个参数。

如果您不包含它,User函数将返回部分应用的函数,该函数仍然需要Bool才能返回正确的用户。即使所有类型和函数都有适当的注释,编译器似乎也会被抛弃。

导致更好的错误消息的另一种方法是定义newUser,如下所示:

newUser =
    { id = randomId
    , name = model.name
    , age = ageAsInt
    , deleted = False
    }