Elm: значение доступа пользовательского типа - PullRequest
1 голос
/ 21 апреля 2020

У меня есть собственный тип в Elm для обработки ошибок ветвления. По сути, у меня есть вход, который дает String с, и мне нужно преобразовать его в Int с.

type Seconds
    = Error Int
    | Valid Int

type alias Model =
    { timeBetweenExercises : Seconds
    , roundsSequenceOne : Seconds
    , roundsSequenceTwo : Seconds
    , roundsSequenceThree : Seconds
    , repititionsPerExercise : Seconds
    , secondsPerExercise : Seconds
    , totalTrainingDuration : Seconds
    }


init : Model
init =
    { timeBetweenExercises = Valid 3
    , roundsSequenceOne = Valid 3
    , roundsSequenceTwo = Valid 3
    , roundsSequenceThree = Valid 3
    , repetitionsPerExercise = Valid 6
    , secondsPerExercise = Valid 6
    , totalTrainingDuration = Valid 6
    }

Я получил идею для пользовательского типа из Эвана "Жизнь файл "talk ". Я хочу запомнить номер при возникновении ошибки (например, пользователь ввел строку вместо числа). Вот попытка моей функции обновления:

update : Msg -> Model -> Model
update msg model =
    case msg of
        TimeBetweenExercisesChanged newTime ->
            case String.toInt newTime of
                Nothing ->
                    { model | timeBetweenExercises = Error model.timeBetweenExercises }

                Just time ->
                    { model | timeBetweenExercises = Valid time }

Моя проблема в том, что компилятор кричит на меня, потому что model.timeBetweenExercises имеет тип Seconds. Есть ли способ получить только значение Int пользовательского типа?

1 Ответ

3 голосов
/ 21 апреля 2020

Мне кажется, что модель неверна по двум причинам:

  1. Если у вас есть значение, которое является общим для всех случаев, обычно его удобнее убрать и вверх на уровень.

  2. Ваша функция обновления предполагает, что состояние Error на самом деле не описывает значение, которое оно содержит, поскольку вы просто выбрасываете newTime, если оно недопустимо и используется вместо этого использовалось старое время для дела Error.

Исходя из этого, я бы предложил вместо этого следующую модель:

type alias TimeInput =
    { seconds: Int
    . state: TimeInputState
    }

type TimeInputState = Error | Valid

type alias Model =
    { timeBetweenExercises : TimeInput
      ...
    }

и изменил ваше обновление функция для этого:

update : Msg -> Model -> Model
update msg model =
    case msg of
        TimeBetweenExercisesChanged newTime ->
            case String.toInt newTime of
                Nothing ->
                    { model
                        | timeBetweenExercises = 
                            { seconds: timeBetweenExercises.seconds
                            , state: Error
                            }
                    }

                Just time ->
                    { model
                        | timeBetweenExercises = 
                            { seconds: time
                            , state: Valid
                            }
                    }

В противном случае вы всегда можете просто сделать функцию для извлечения Int независимо от случая:

getSeconds : Seconds -> Int
getSeconds time =
    case time of
        Error seconds -> seconds
        Valid seconds -> seconds
...