ELM: транслитерационная строка - PullRequest
0 голосов
/ 11 ноября 2018

Я совершенно новый в ELM. Теперь я пытаюсь преобразовать некоторую строку (которую я получаю из json) в русский перевод. Например Италия -> Италия.

countryConvert : String -> String
countriesTransliterationMap country =
    case country of
        italy -> "Италия"
        canada -> "Канада"

Но теперь я получаю

Any value with this shape will be handled by a previous pattern, so it should be
removed.

Что не так с моим кодом?

1 Ответ

0 голосов
/ 11 ноября 2018

Ваш код, как указано, не выдает ошибку, о которой вы сказали. Однако, если я немного его почистю, появится ошибка:

italy : String
italy = "italy"

canada : String
canada = "canada"

countryConvert : String -> String
countryConvert country =
    case country of
        italy -> "Италия"
        canada -> "Канада"

Чтобы быть более точным, он выдает эту ошибку с Elm 0.18. Если вы попытаетесь скомпилировать с 0.19, вы получите чуть более информативную ошибку:

$ elm make Countries.elm 
The name `italy` is first defined here:

5| italy = "italy"
   ^^^^^
But then it is defined AGAIN over here:

17|         italy -> "Италия"
            ^^^^^
Think of a more helpful name for one of them and you should be all set!

Это все еще может быть немного загадочным, хотя. Главное, что нужно понять, это то, что выражения case имеют две цели, которые иногда пересекаются: сравнивать отдельные значения или с test значения структуры («форма», на языке сообщения об ошибке 0,18) и значения «деструктура» - присвоение локальных имен частям этой структуры. В руководстве Вяза есть хороший простой пример .

Для сравнения отдельных значений эти значения должны быть in-line в каждом предложении выражения case. Предполагается, что любые переменные, которые вы используете, являются новыми объявлениями , локальными по отношению к этому предложению выражения case.

Таким образом, в вашем выражении case вы не сопоставляете значения, которые italy и canada имеют в остальной части вашей программы. Вместо этого вы объявляете две новые локальные переменные , которые просто случаются с , а также с именами italy и canada. Другими словами, вы вообще не «разбирали» строку country - все, что вы сделали, это просто объявили для нее новое локальное имя (italy). И именно поэтому 0.19 жалуется на слежку. (См. это объяснение , почему теневое копирование является ошибкой, а не просто предупреждением в 0.19.)

Поскольку также нет структурной разницы между предложениями выражения case, 0.18 фактически жалуется на то, что ваши два предложения case идентичны. Каждый будет соответствовать любой строке и назначать ее новой локальной переменной italy; другая также будет соответствовать любой строке и присвоит ее новой локальной переменной canada.

Альтернативы, которые будут работать:

Вы можете просто вставить значения:

countryConvert : String -> String
countryConvert country =
    case country of
        "italy" -> "Италия"
        "canada" -> "Канада"
        _ -> country

Вы можете использовать простую конструкцию if-else:

countryConvert : String -> String
countryConvert country =
    if country == italy then
        "Италия"

    else if country == canada then
        "Канада"

    else
        country

Или используйте Dict:

countries : Dict String String
countries =
    fromList
        [ ( "italy", "Италия" )
        , ( "canada", "Канада" )
        ]


countryConvert : String -> String
countryConvert country =
    case get country countries of
        Just c ->
            c

        Nothing ->
            country

Обратите внимание, что вам все еще нужно выражение case с этим подходом. Это потому, что Dict.get может быть передан ключ, которого нет в Dict. Таким образом, вы можете рассмотреть возможность использования типа возврата вашей функции Maybe String, чтобы было ясно, что вызывающая сторона может переехать в страну, которую вы не знаете как перевести. И это обязанность вызывающего абонента решить, что делать в этом случае.

...