Функция конвертировать из позиции в элемент - PullRequest
3 голосов
/ 20 февраля 2012

У меня есть этот список объединить: list + undefined list Я пишу эту функцию, чтобы вернуть элемент оттуда позиции.

let name_of_num list undefined_list len_undefined k =
  if k < len_undefined then List.nth undefined_list k else
    List.nth list (k - len_undefined)

val name_of_num : 'a list -> 'a list -> int -> int -> 'a

Но моя проблема в том, что когда я применяю свою функцию, список имеет тип, отличный от неопределенного списка. Так что эта функция не может пройти компилятор. где undefined - это список строк.

let len_undefined xsds = List.length (undefined xsds)

let xsds_of_int xsds =
List.map (List.map (name_of_num xsds undefined (len_undefined xsds)))

xsds имеет тип xsds в моей программе. Если бы я заменил undefined на xsds, как эта функция:

let xsds_of_int xsds =
List.map (List.map (name_of_num xsds xsds (len_undefined xsds)))

это работает. Как я могу написать второе условие, когда k < len_undefined?

let name_of_num list len_undefined k =
  if k < len_undefined then ??? else
    List.nth list (k - len_undefined)

Спасибо.

1 Ответ

3 голосов
/ 20 февраля 2012

То, что вы просите, кажется невозможным. Вы хотели бы предоставить два списка разных типов. Но ваша функция иногда возвращает элемент list, а иногда возвращает элемент undefined_list. Поскольку OCaml является строго типизированным языком, функция всегда должна возвращать значения одного и того же типа. Отсюда следует, что list и undefined_list должны иметь одинаковый тип.

Трудно понять, что предложить, не понимая ваших требований. Тем не менее, очень просто определить новый тип, который объединяет любые два типа, которые вам нравятся. (Или любое конечное число типов.)

type either = A of typea | B of typeb

Значение (A x) представляет значение typea, а значение (B y) представляет значение typeb. Но эти два значения одного типа, типа either.

Затем вы определяете name_of_num для двух списков разных типов, но он возвращает тип either. Если вы хотите стать более любопытным, вы можете определить either как параметризованный тип, что позволило бы name_of_num быть полиморфным. Хорошо ли это делать, зависит от проблемы, которую вы пытаетесь решить.

Я не уверен, что это решит вашу проблему, но я надеюсь, что это поможет.

Редактировать

Вот как будет выглядеть ваша функция, если вы используете тип either. Больной используйте int для одного типа и string для другого.

type either = A of int | B of string

let name_of_num list undefined_list len_undefined k =
  if k < len_undefined then
    (B (List.nth undefined_list k))
  else
    (A (List.nth list (k - len_undefined)))

val name_of_num : int list -> string list -> int -> int -> either = <fun>
# 

Редактировать 2

Меня поражает, что вы можете использовать исключение для решения вашей проблемы. Если вы пытаетесь заполнить матрицу сопоставленных значений, и если входные данные вне диапазона являются редкими (и указывают на ошибку), вы можете просто вызвать исключение, если вы видите неправильный ввод. Абонент может поймать исключение и решить, что делать. Тогда ваша функция name_of_num всегда будет возвращать xsd. (Если он видит плохое значение, он вообще не возвращается.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...