Спецификация списка с более чем одним определенным элементом

#erlang

#erlang

Вопрос:

Я проанализировал список json, и он выходит с каждым элементом, например:

 {struct,
 [
  {<<"name">>, "<<a name>>"},
  {<<"id">>, "<<an id>>""}
 ]
}
  

Я хотел бы указать это как тип, но я получаю сообщение об ошибке со следующим, предположительно потому, что я использую два элемента в определении списка:

 -type user_data() :: {struct, [{Name_key::Binary, Name_value::Binary},{ID_key::Binary, ID_value::Binary}]}.
  

Есть ли какой-нибудь способ сделать то, что я пытаюсь сделать?

Ответ №1:

Вы можете сделать

 -type user_data() :: {struct, [{Name_key::binary(), Name_value::binary()}|{ID_key::binary(), ID_value::binary()}]}.
  

имеется в виду список, каждый элемент которого является либо a {Name_key::binary(), Name_value::binary()} , либо an {ID_key::binary(), ID_value::binary()} . Это не совсем то, что вы хотите, но может быть достаточно хорошим.

Ответ №2:

Как вы указываете, когда вы указываете типы элементов в списках, может быть указан только один тип. Дополнительные типы могут быть добавлены с использованием синтаксиса объединения, но внутренне это не сохранит информацию о порядке элементов в списке.

Так что лучше всего сделать что-то вроде:

 -type user_data :: {struct, [{Key::binary(), Value::binary()}]}.
  

Вы также можете попробовать:

 -type      field() :: {Key::binary(), Value::binary()}.
-type name_field() :: field(). % Key is <<name>>
-type   id_field() :: field(). % Key is <<id>>
-type     fields() :: [name_field() | id_field()].
-type  user_data() :: {struct, fields()}.
  

В этом последнем примере сохраняется вся информация, и вы можете расширить ее разумным образом.

Ответ №3:

В большинстве систем типов список like [A, B] считается мономорфным в том смысле, что A и B должен иметь один и тот же тип. Это относится и к системе типа диализатора Erlangs. чтобы сделать возможным представление этого как отдельных типов, представление должно быть произведением типов, сформированных с помощью кортежа, {A, B} который неявно также говорит, что всегда есть ровно два элемента, а именно A и B и они всегда встречаются вместе.

Однако существуют системы типов, которые позволяют вам иметь полиморфные списки. Одним из способов является кодирование элементов как экзистенциальных типов. Представьте, что элементы A и B «упакованы» таким образом, что их внутреннее представление непрозрачно для вас, и единственный способ, которым вы можете манипулировать ими, — это использовать некоторые предопределенные функции, указанные пакетом. Другой способ — использовать расширенные системы типов, обычно с зависимыми типами, где ваш тип определяется структурой списка.