Как обрабатывать список полиморфных вариантов? - PullRequest
3 голосов
/ 04 марта 2012

Позвольте двум вариантным типам:

type typeA = 
    | A1 
    | A2
;;  

type typeB = 
    | B1 of typeA
    | B2 of typeA
;;  

и функциям проверки типов:

let isA1 = function A1 -> true | _ -> false;;
let isA2 = function A2 -> true | _ -> false;;   
let isB1 = function B1 e -> true | _ -> false;;
let isB2 = function B2 e -> true | _ -> false;; 

Я хотел бы создать список этих функций для проверки элементов типа A илиB

, поскольку они разных типов, мне нужны полиморфные варианты, и я получаю:

type filterA =
{
    handleA : typeA -> bool;
};;

type filterB =
{
    handleB : typeB -> bool;
};;

type filterslist = [`FilterA of filterA | `FilterB of filterB] list ;;

let filters1 = [`FilterA { handleA = isA1 }; `FilterB { handleB = isB1 }] ;;

Итак, теперь я хочу перебрать filters1 для проверки типа аргумента, который я пробовал:

let exec_filters filters event = List.iter (fun fil -> match fil with `FilterA -> fil.handleA event; ()| `FilterB -> fil.handleB event; () ) filters;;

но это не оценено:

Error: This expression has type [< `FilterA | `FilterB ]
       but an expression was expected of type filterA

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

Ответы [ 3 ]

5 голосов
/ 04 марта 2012

Тот факт, что вы используете «предикаты проверки типов», подобные Scheme или instanceOf, указывает на то, что, вероятно, что-то не так с вашим кодом. OCaml - это статически типизированный язык, вы не должны:

итерируйте по фильтрам1, чтобы проверить тип аргумента, который я пробовал

Почему ты это делаешь? Если вы пытаетесь обрабатывать несколько типов, способ сделать это - использовать полиморфизм. Полиморфные варианты могут быть полезны для этого, но я все еще не уверен, что ваш код не просто написан странным образом.

4 голосов
/ 04 марта 2012

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

let exec_filters filters event =
  List.iter
    (fun fil -> match fil with
      | `FilterA fA -> fA.handleA event; ()
      | `FilterB fB -> fB.handleB event; () )
    filters;;

РЕДАКТИРОВАТЬ: Однако это не будет проверка типов, так как event не может иметь типы typeA и typeB ...

Почему бы не сделать ваши первоначальные варианты (typeA и typeB) полиморфными?

Что вы пытаетесь сделать?

2 голосов
/ 04 марта 2012

Когда вы говорите

match fil with
`FilterA -> ...

Вы, кажется, ожидаете, что это изменит тип fil, но это не так.Выражение с типом filterA появляется внутри шаблона.Вы хотите что-то похожее на это:

match fil with
`FilterA { handleA = h } -> h event

Я не уверен, что вижу цель, чтобы ваши обработчики возвращали bool, если вы собираетесь использовать List.iter для их выполнения.Это вернет unit, и значения bool будут отброшены.

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

Существует более глубокая проблема типизации, хорошо объясненная Ptival.Поэтому, даже если вы исправите свои схемы, вам все равно придется пересмотреть свой план.Одна из возможных вещей - использовать варианты (кстати, не обязательно полиморфные) для отслеживания типов событий.

...