3
votes

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 ?

3
"as they're of different types, I need polymorphic variants" -- nope. If you give us the real stuff you're working with, we're better able to help you, but it seems you're creating more work for yourself here.Asherah

3 Answers

5
votes

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.

4
votes

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?

2
votes

When you say

match fil with
`FilterA -> ...

You seem to expect that this will change the type of fil, but that's not how it works. The expression with the type filterA appears inside the pattern. You want something more like this:

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

I'm not sure I see the purpose of having your handlers return bool if you're going to use List.iter to execute them. This will return unit, and the bool values are going to be discarded.

Edit

There's a deeper typing problem, explained well by Ptival. So even if you fix your patterns you'll still need to rethink your plan. One possible thing to do would be to use variants (not necessarily polymorphic variants, by the way) to track the types of the events.