telesphore4
telesphore4

Reputation: 887

F#: Odd type inference behavior

First off, I have a better method of dealing with this issue so it's not a problem.

However, it is something that I don't understand. Can someone explain this?

When I define the swap function as:

namespace Utilities
module Misc

let Swap (left : 'a byref) (right : 'a byref) =
    let temp = left
    left  <- right
    right <- temp

I am able to use the Swap function like this just fine.

Misc.Swap (&s.[i]) (&s.[j])

But when I define the module like:

namespace Utilities

type Misc =
    static member Swap (left : 'a byref) (right : 'a byref) =
        let temp = left
        left  <- right
        right <- temp

I get the following error on both arguments:

This expression has type  'b byref but is here used with type  'a ref

How did the type inference for the caller's arguments change by moving the function into a type?

Upvotes: 2

Views: 188

Answers (1)

Daniel Asher
Daniel Asher

Reputation: 1503

This may be an interaction with the tuple transformation that the F# compiler performs on class methods.

Reflector reports the type of Misc.Swap as:

public static void Swap<a>(ref a left, ref a right);

so we can see here that the compiler has transformed the curried arguments into tupled form.

Defining the method with tupled arguments avoids this problem:

type Misc =
    static member Swap(left : 'a byref, right : 'a byref) =
        let temp = left
        left  <- right
        right <- temp    

> let s = Array.init 3 (fun i -> i)
> val s : int array = [|0; 1; 2|]
> Misc.Swap (&s.[2], &s.[0]) 
> s;;
> val s : int array = [|2; 1; 0|]

Upvotes: 2

Related Questions