Is it possible to make this completely polymorphic in OCaml?

in OCaml

let nth_diff_type i (x, y, z) = match i with 1 -> x |2 -> y |3 -> z |_ -> raise (Invalid_argument "nth") 

So, the current type is int->('a,'a,'a)->'a , right?

It follows that x, y, z must be of the same type.

So my question is, can I give it max polymorphic , so that x, y, z do not have to be of the same type?

+4
source share
3 answers

No, it is not.

A function in OCaml must have only one return type. You may have different types of arguments if your return type is unique:

 let nth_diff_type i (x, y, z) = match i with | 1 -> `Fst x | 2 -> `Snd y | 3 -> `Thd z |_ -> raise (Invalid_argument "nth") // val nth_diff_type : // int -> 'a * 'b * 'c -> [> `Fst of 'a | `Snd of 'b | `Thd of 'c ] = <fun> 

If you want to create several utility functions for triplets, unfortunately, you have to define them separately:

 let fst3 (x, _, _) = x let snd3 (_, y, _) = y let thd3 (_, _, z) = z 
+8
source

If your function was to apply an arbitrary function f to an arbitrary element of a tuple, for example, the function f is of the correct type, then you could make this polymorphism to some extent.

In other words, if you think about what you can do with your function, you will come to the conclusion that you will need a function of the correct type to apply it to the result of nth_diff_type , regardless of what the type may be.

If we assume for a moment that nth_diff_type works with any tuple, its result is potentially any type. You can get int , a string or instances of more complex data types. Let me call this type t . Then what can you do with a value of type t ? You can only pass it to a function that takes t values.

So, now the problem is choosing the right function, and this choice will certainly be made according to very similar criteria than the rank of the element inside your tuple. If so, why not just pass in your tuple and tuple of functions that could be applied to nth_diff_type and let it make the application on its own?

 let nth_diff_type i (a,b,c) (fa,fb,fc) = match i with | 1 -> fa a | 2 -> fb b | 3 -> fc c | _ -> failwith "out of range" -: val nth_diff_type : int -> ( 'a * 'b * 'c) -> (('a -> 'd) * ('b -> 'd) * ('c -> 'd)) -> 'd 
+2
source

The code is already completely polymorphic on type-independent systems. You can go to a system of a dependent type (but you probably don't want to, because of the complexity of the complexity), where the type will look something like this:

 (n : int) -> (a * b * c) -> (match n with 1 -> a | 2 -> b | 3 -> c | _ -> Error) 

In addition to offering the pad, you can also use the type of record or object to have a direct โ€œprojectionโ€ operation instead of first defining it by matching patterns.

 type ('a, 'b, 'c) triple = { nth1 : 'a; nth2 : 'b; nth3 : 'c } (* replace *) nth_diff_type 2 v (* by *) v.nth2 

With the type of object (which adds a structural flavor that does not have to be predefined)

  (* replace *) nth_diff_type 2 v (* by *) v#nth2 

Note that this replacement only works with constant integers (since otherwise you need an integer-> type type dependency). You could solve something using GADT and existential types to support passing certain choices, but you have to pay a huge cost of complexity for what is more likely due to the fact that you are not familiar enough with the existing simple type system to understand how you really want to do something.

+1
source

All Articles