Как развернуть псевдоним универсального типа из типа объединения, который делает псевдоним типа более конкретным? - PullRequest
1 голос
/ 08 марта 2019

У меня есть тип Model, который описывает два возможных состояния универсального псевдонима типа ModelFields.И я хочу извлечь обобщенную ModelFields запись из экземпляра типа Model.

type Model endValue stats
  = ShowEndValues (ModelFields Organism endValue)
  | ShowStatistics (ModelFields Rank stats)

type alias ModelFields object results =
  { results : List results
  , objects : List object
  , cellValue : results -> String
  , location : Maybe (Rank, Rank)
  }

getModelFields : Model endValue stats -> ModelFields object results
getModelFields model =
  case model of
    ShowEndValues modelFields ->
      modelFields 
    ShowStatistics modelFields ->
      modelFields

Но Элм не позволяет ему говорить для каждого выражения case, что

TYPE MISMATCH - Something is off with the 1st branch of this `case` expression:

55|       modelFields 
          #^^^^^^^^^^^#
This `modelFields` value is a:

    ModelFields #Organism# #endValue#

But the type annotation on `getModelFields` says it should be:

    ModelFields #object# #results#

#Hint#: Your type annotation uses type variable `object` which means ANY type of
value can flow through, but your code is saying it specifically wants a
`Organism` value. Maybe change your type annotation to be more specific? Maybe
change the code to be more general?

Итак, мой вопрос: как мне получить ModelFields от Model?Или я делаю что-то принципиально некорректное?

UPD.Подробности того, что я пытаюсь смоделировать.

У меня есть объекты типа Organism.Они сгруппированы в Rank с.Мой сервер выполняет парный анализ Organism с, ig вычисляет Similarity и Distance между двумя Organism с.Я хотел бы отобразить результаты этих анализов в двух таблицах на разных страницах, одна страница для анализа Similarity и одна страница для анализа Distance.Это означает, что таблица должна быть многоразовой, чтобы принимать результаты анализа любой формы.С другой стороны, существует один общий шаблон для этих таблиц.Они могут находиться в двух состояниях:

  1. Показаны конкретные результаты парных сравнений (endValue в Model) между Organism с, поэтому строки и столбцы таблицы представляют Organism с.
  2. Отображение статистических значений (например, среднее или стандартное отклонение, stats в Model) между группами (Rank с) Organism с, в этом случае строки и столбцы таблицы представляют Rank с.

То, какие Rank с или Organism с отображаются, зависит от поля location ModelFields.Пользователь может нажать кнопку, и я хотел бы изменить location в моей update функции.Потенциально это изменение навигации может переключаться между состояниями ShowEndValues и ShowStatistics.Вот почему я пытаюсь развернуть ModelFields из Model конструкторов.Я прилагаю простую иллюстрацию в надежде, что это поможет уточнить. table illustration

1 Ответ

1 голос
/ 08 марта 2019

Это действительно невозможно.

Значение model в функции getModelFields будет иметь тип Model endValue stats. Это означает, что это будет либо вариант ShowEndValues, содержащий значение типа ModelFields Organism endValue, либо вариант ShowStatistics, содержащий значение типа ModelFields Rank stats. Каждая ветвь выражения case распаковывает один вариант и выводит значение modelFields.

Теперь давайте попробуем определить тип выражения case. Мы смотрим на типы, возвращаемые каждой ветвью, и пытаемся найти тип, который охватывает оба типа (объедините их). На первый взгляд, это выглядит многообещающе: оба значения имеют форму ModelFields a b, поэтому мы будем рекурсивно пытаться объединить каждый из дочерних типов. Здесь мы сталкиваемся с проблемой - a первого типа имеет тип Organism, тогда как второй - Rank. Не существует типа Organism и Rank, поэтому компиляция не удалась.

Примечание. Как видно из сообщения об ошибке, Elm на самом деле пытается объединить типы ветвей с типом результата функции. (Я описал другое направление, потому что я думаю, что это более понятно для понимания.) Направление, которому следует Элм, также терпит неудачу, потому что оно будет повторяться и пытаться объединить конкретный тип Organism с общим типом object, аналогично тому, как мы пытались объединить два конкретных типа.

...