Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OCaml unexpected type mismatch in tuples

I'm trying to write a function, that takes an integer and a triplet and returns an element of the triplet at the given position (exercise 5.3 from Hickey's book). Triplet should be able to contain elements of different types.

I thought, that if I write 3 little functions, each returning a specific element of the triple and make my big function return one of them accordingly, then it would do the trick, but it doesn't work.

I've tried to fiddle with this "eta-expansion" concept, but I didn't get it.

let nth1 (a, _, _) = a
let nth2 (_, b, _) = b
let nth3 (_, _, c) = c

let nth i = match i with
    | 1 -> nth1
    | 2 -> nth2
    | _ -> nth3

let main = printf "%d\n" (nth 1 ("hello", 2, 'c'))

So it should just write "2" here. Any advice?

like image 352
user1714986 Avatar asked Oct 02 '12 17:10

user1714986


2 Answers

The basic answer to your question:

In OCaml, the way the type system works will force nth to return only a single type. What you want is something resembling an intersection type, but the static type semantics for OCaml will instead force nth to return only a single type. The upshot of this is that your tuple must degenerate into the case where element is the same type.

Let's consider this interaction:

# let nth1 (a,_,_) =a;;
val nth1 : 'a * 'b * 'c -> 'a = <fun>
# let nth2 (_,b,_) = b;;
val nth2 : 'a * 'b * 'c -> 'b = <fun>
# let nth3 (_,_,c) = c;;
val nth3 : 'a * 'b * 'c -> 'c = <fun>
# let nth i = match i with
      | 1 -> nth1
      | 2 -> nth2
      | _ -> nth3;;
val nth : int -> 'a * 'a * 'a -> 'a = <fun>

So your question is strange, not because of the printf call, but instead, because of the definition of nth. Instead you might look into making a unique type which is the combination of a few of these types.

Indeed, the kind of behavior you describe feels a little bit like dependent types, where the type you get actually depends on the value of the input i. This should naturally be problematic, as dependent typing is much more expressive than the let bound polymorphism seen in ML!

I will say, that you can do this for instances of tuples, for example, you can make a type:

type IntOrStringOrX = int | string | X

and then you can correspondingly write down a type of nth...

like image 189
Kristopher Micinski Avatar answered Dec 02 '22 06:12

Kristopher Micinski


It usually helps to think about types before writing code. What is the proposed type of your function?

like image 32
Jeffrey Scofield Avatar answered Dec 02 '22 06:12

Jeffrey Scofield