Ref list of functions

Why compiler throws an error for ref list of tuples of function and string?

let attrList:((('a -> bool) * 'c) list) ref = ref []

Error:The type of this expression, ((’_a -> bool) * '_c) list Batteries.ref,
contains type variables that cannot be generalized

The problem is that the type that you wrote is not precise enough: the type of a mutable field or a reference must be a concrete type with no free type variables in a given compilation unit. Indeed since a mutable value can be wrote to and read from, it must always give a consistent view of its content. You can look at the reference manual for a more detailed explanation.

1 Like

How should I make it precise?

1 Like

By writing the type of the elements of the list.

And you cannot have a non-empty list with an element of type 'c for all type 'c, because this type has no inhabitant. In other words, a real value cannot be simultaneously an int and a float and a string and etc.

Similarly, without playing tricks, the only functions with type 'a -> bool, for any 'a, are fun _ -> true and fun _ -> false.

1 Like

I tried to make precise type annotations using two methods -

I tried both these methods -
By giving an actual example of the list

let attrList = ref [((fun (l,n) -> n > 0), “n > 0”)]

I get this error for this -

The type of this expression,
((’_weak1 * int -> bool) * string) list Batteries.ref,
contains type variables that cannot be generalized
makefile:4: recipe for target 'dep-only’ failed

By giving precise type annotations -

let attrList:((((fun (_) -> bool) * string) list) ref) = ref []

I get syntax error for this one -

File “pie.ml”, line 11, characters 17-20:
Error: Syntax error
makefile:4: recipe for target ‘dep-only’ failed
make: *** [dep-only] Error 2

What is the type of the first argument (l) ?

int, but the thing is the number of arguments can change and they can be list or int.

List are homogeneous in OCaml, the type of elements cannot change ( and even with heterogeneous list, a reference containing such list will have a constant type itself).

The correct syntax for type annotation is:

let attrList: ( ( int -> int -> bool ) * string) list ref = ref []

If you want to have varying number of argument, that can either int of list of ints, you should use a variant

type arg = List of int list | Single of int

and makes the stored functions takes a list of args

let attrList: ( ( arg list -> bool) * string) list ref = ref []

Awesome, thank you so much.

I suppose you need to learn this document https://caml.inria.fr/pub/docs/manual-ocaml/polymorphism.html

So I have -

type arg = List of int list | Single of int
let attrList: ( ( arg list -> bool) * string) list ref = ref []

Now I want to append items to attrList using pattern matching -

let rec createAttributeList features =
match features with
[] -> attrList := attrList.contents
|(a,b)::tl -> if (true) then (attrList := (a,b)::attrList.contents) else (createAttributeList tl)

here ‘a’ can be a function with a single argument or two arguments - it could be int or list of int.

How can I accomplish this? Basically, I am adding items from the local list to global list. both lists have same format.

You should have a look at List.iter, List.filter, and List.map . Moreover, rather than updating the global reference at each step, you should write a function that append together two lists and then uses this function to update the global reference. (and are you sure that you need such global state?). Finally, you should specify what you are trying to do and what is not working rather than what mechanism you are trying to use.