Reputation: 53
I would like to write a function which takes several tupples as arguments and choose theirs ith elements and passes to another function, where i is given as another argument. I've tried sth like this:
let function (tup1:'A*'A) (tup2:'B*'B) i =
otherFunction (i tup1) (i tup2)
function Tup1 Tup2 fst
I've got an error, because i
was expected to be 'A*'A ->'A
not 'B*'B->'B
.
Is it any way to make this code to work?
Thanks in advance.
Upvotes: 5
Views: 137
Reputation: 55185
You basically want to pass an argument of type ∀'a.'a*'a->'a
, but in F# (and other MLs), only rank-1 polymorphism is supported so you can't do this directly. The workaround is to define a new type with a generic method to emulate higher-rank polymorphism:
type Untupler =
abstract Apply : 'a*'a -> 'a
let myFunction tup1 tup2 (i:Untupler) =
otherFunction (i.Apply tup1) (i.Apply tup2)
myFunction Tup1 Tup2 { new Untupler with member __.Apply (x,y) = x }
Upvotes: 4
Reputation: 233495
When you use the function i
with tup1
, it's inferred to be of the type 'A * 'A -> 'A
. This means that when you use it with tup2
, the only way that can work is if tup2
is also an 'A * 'A
.
The function i
can't change type within the same function. If there's a way to do what you want, I'm not aware of it, but you can sidestep the issue like this:
let myFunction x y =
otherFunction x y
Call it like this:
myFunction (fst tup1) (fst tup2)
This puts slightly more responsibility of the caller, but the advantage is that it's possible :)
Upvotes: 3