Соответствие шаблону определяемого пользователем типа Ocaml

#ocaml

#ocaml

Вопрос:

Вот мое определение типа:

 type ('type1, 'type2) symbol =
  | N of 'type1
  | T of 'type2
  

Вот несколько типов:

 type mysub =| Abc | Bcd | Def
  

У меня также есть список [N Abc;N Bcd; T"("] .

Что я хочу сделать, так это выбросить все элементы типа T , а также выбросить 'type1 или 'type2 . Таким образом, желаемый результат [Abc; Bcd]

Но когда я пробую этот фрагмент кода:

 List.map (fun x-> match x with N (a)->a |T (b) ->b ) (List.filter (fun x->match x with
N (type1) ->true |T (type2) -> false) [N Abc;N Bcd; T"("]);;
  

это дает мне следующее сообщение:

 Error: This expression has type (mysub, string) symbol list
       but an expression was expected of type
         (mysub, mysub) symbol list
       Type string is not compatible with type mysub.
  

Как я могу это исправить?

Ответ №1:

В этом фрагменте

 List.map
    (fun x -> match x with
    N a -> a
    T b -> b
    )
  

Возвращаемые типы не совпадают для двух случаев совпадения. Если T b бы в списке были какие-либо элементы, это была b бы строка, и компилятор не знает, что таких элементов нет. Поскольку вы знаете, что их нет, вы можете исправить это, предоставив что-то другое, кроме b результата для этого случая. Что-то вроде этого:

 List.map
    (fun x -> match x with
    N a -> a
    T _ -> Abc
    )
  

Или даже это:

 List.map
    (fun x -> match x with
    N a -> a
    T _ -> failwith "This can't happen"
    )
  

Комментарии:

1. Это бандаж. Правильное решение — использовать не композицию map и filter, а более богатую версию, например filter_map ( ('a -> 'b option) -> 'a list -> 'b list ) или flatmap .