4
votes
let a = ref 0
let f (x: byref<int>) = x

f a // type error

System.Int32.TryParse("123",a) // works

f a being a type error is puzzling to me since a can be passed into .NET library methods with a byref<int> type. Why?

Edit: I think I really explained the question poorly. The type of System.Int32.TryParse is string * byref<int> -> bool and yet it works. So why can't I pass a into a function of type x:byref<int> -> int? That is all I am asking.

2
What's the exact error?TheQuickBrownFox
error FS0001: This expression was expected to have type byref<int> but here has type int refMarko Grdinić
I understand that the compiler is converting the reference to byref in the call to TryParse. What I am wondering is why isn't it doing for functions on the F# side?Marko Grdinić
@rmunn No, I can't see this particular example being addressed in the question you linked.Marko Grdinić

2 Answers

5
votes

This feature is described in section 8.13.7 of the F# spec. The ability to use a ref when a byref is expected is enabled by a "type-directed conversion", but these are applied only on member invocations, not on regular function applications.

1
votes

The only thing I am seeing wrong with that code is the Type Annotation is incorrect, try :int ref instead of byref<int>

Full code:

let a = ref 0
let f (x: int ref) = x

f a // type error

System.Int32.TryParse("123",a) // works

Edit: Sorry, I misunderstood your question. So this one is a bit vague on F#'s part, I do think F# needs to improve it's error messages a bit. What is happening is since C# did not originally have tuples, they needed out parameters in order to return multiple values. So when you see a signature like byref<int>, that is .NET's way of telling you that is the signature of an out parameter, out parameters are for C# only. More reading here.