#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 .