Доступ к записи после фильтрации списка типа сумма - PullRequest
3 голосов
/ 13 июля 2011

У меня есть список

type my_sum = {a : type_a} / {b : type_b}
mylist = [{field_only_in_a = "test"} : type_a,{haha=3 ; fsd=4} : type_b]

Я хочу сделать это:

result = List.find( a -> match a with 
                                      | {a = _} -> true
                                      | _ -> false
                                     end,
                                mylist)
 if Option.is_some(result) then
     Option.some(Option.get(result).field_only_in_a)
 else
     Option.none

Как вы можете видеть, после поиска я обязательно получу что-то от type_a но во время компиляции я получаю это:

    Record has type
{ a : type_a } / { b : type_b }  but field access expected it to have type
{ field_only_in_a: 'a; 'r.a }
Hint:
  You tried to access a sum type with several cases as a record.

Как я могу сказать компилятору, что у меня есть только один тип типа суммы и у меня есть хороший тип для доступа к записи ....?

1 Ответ

4 голосов
/ 13 июля 2011

Ну, вы не можете сообщить компилятору, что в списке будет существовать только подтип ... но вы можете явно создать список только с этим подтипом. Фактически, вы ищете List.find_map, который находит первый элемент, соответствующий определенным критериям, и отображает его (вы используете это отображение для проецирования из my_sum в его регистр type_a). Ниже приведен полностью рабочий код (компилируется самостоятельно):

type type_a = {fld_a : string}
type type_b = {fld_b : int}
type my_sum = {a : type_a} / {b : type_b}

mylist = [{a = {fld_a = "test"}}, {b = {fld_b = 10}}] : list(my_sum)

get_first_a(l : list(my_sum)) : option(type_a) =
  List.find_map(
    (el -> match el
           | ~{a} -> some(a)
           | _ -> none
    ), l)

_ = prerr("First a-typed element of {mylist} is {get_first_a(mylist)}\n")

Если бы в stdlib не было функции List.find_map, все равно было бы множество способов сделать это. Вероятно, самым простым было бы использовать List.filter_map для получения list(type_a), а затем получить его голову с List.head_opt.

...