Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How handling a list of polymorphic variants?

Let two variant types :

type typeA = 
    | A1 
    | A2
;;  

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

and type-checking functions :

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

I'd like to create a list of those functions to check elements of type A or B

as they're of different types, I need polymorphic variants and I get :

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

So now I want to iterate over filters1 to check the type of the argument I tried :

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

but it's not appreciated :

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

How can I handle this ?

like image 717
codablank1 Avatar asked Jan 20 '26 13:01

codablank1


2 Answers

The fact that you're using "type checking predicates" similar to Scheme or instanceOf indicates that there is probably something very wrong with your code. OCaml is a statically typed language, you should not:

iterate over filters1 to check the type of the argument I tried

Why are you doing this? If you are trying to handle multiple types, the way to do it is to use polymorphism. Polymorphic variants can be helpful for this, but I'm still not convinced that your code isn't just written in a strange way.

like image 171
Kristopher Micinski Avatar answered Jan 23 '26 05:01

Kristopher Micinski


I think your code should read like:

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

EDIT: However, this won't typecheck, since event can't have types typeA and typeB...

Why not make your initial variants (typeA and typeB) polymorphic?

What are you trying to do?

like image 34
Ptival Avatar answered Jan 23 '26 04:01

Ptival