Как работать со списком полиморфных вариантов?

Пусть два варианта типа:

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 }] ;;

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

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

Как мне с этим справиться?


person codablank1    schedule 04.03.2012    source источник
comment
так как они разных типов, мне нужны полиморфные варианты - нет. Если вы дадите нам реальный материал, с которым вы работаете, мы сможем лучше вам помочь, но, похоже, вы создаете больше работы для себя здесь.   -  person Asherah    schedule 05.03.2012


Ответы (3)


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

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

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

person Kristopher Micinski    schedule 04.03.2012
comment
на самом деле, я пытаюсь получить своего рода динамическое сопоставление с образцом во время выполнения, поэтому да, я хочу обрабатывать несколько типов, с одной конкретной функцией, запускаемой для каждого из них - person codablank1; 05.03.2012
comment
В этом нет никакого смысла. Вы не можете динамически сопоставлять типы в OCaml: язык так не работает. Вы можете динамически сопоставлять значения типов, это просто старое сопоставление с образцом, но сопоставление типов - это не то, что позволяет язык OCaml. Ваш вопрос все еще не совсем ясен. - person Kristopher Micinski; 05.03.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 и _4 _...

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

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

person Ptival    schedule 04.03.2012
comment
да, я получаю сообщение об ошибке: `| FilterB(fB) -> fB.handleB event; () Error: This expression has type typeA but an expression was expected of type typeB - person codablank1; 05.03.2012

Когда ты говоришь

match fil with
`FilterA -> ...

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

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

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

Изменить

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

person Jeffrey Scofield    schedule 04.03.2012
comment
не компилируется ...: This expression has type typeA but an expression was expected of type typeB - person codablank1; 05.03.2012
comment
Мне нужно посмотреть, что вы скомпилировали. Вы не получите это сообщение для фрагмента выше (я только что проверил). Я расширю код до целой функции, может это прояснит. - person Jeffrey Scofield; 05.03.2012
comment
то же, что и выше, за исключением последней функции: 'let exec_filters Filters filter event = List.iter (fun fil - ›сопоставить fil с | FilterA { handleA = h } -> h event; () | FilterB {handleB = h} -› h event; ()) Filters ;;' - person codablank1; 05.03.2012