My program has a few record types with the same field names (each record type means something different). The compiler insists function parameters matching this record shape must be of the last type declared, even though I'm declaring record instances with unambiguous field names, and always passing a consistent type into each function.
What is the appropriate way to deal with this? I know I could put a type annotation on the functions, but I feel like if I'm doing things the Right Way, I shouldn't need to fight the compiler with type annotations.
Minimum code demonstrating the problem:
type type1 = {x:int}
type type2 = {x:int}
let getX t =
t.x
getX {type1.x=1}
|> ignore
Compiler output:
$ fsharpc --nologo test.fs
/tmp/typetest/test.fs(7,6): error FS0001: This expression was expected to have type
type2
but here has type
type1
You could use a constraint on
getX
:However trying to make it more generic (instead of requiring the property
x
to beint
):has issues with the F# interpreter, compiler and runtime.
The F# interpreter bombs out, the compiler thinks that
getX_generic
returns anobj
instead ofint
, and when you do run it, it does not compute.F# being a new language has a few bugs - if you want this to work - I would suggest you log these issues in a bug report.
There are a few ways around this:
Type annotations as you suggested:
Define
getX
before the conflicting type is defined:Don't explicitly specify the type when calling the function:
Which of these options is the 'right' way depends a lot on the precise situation.
In addition to the answer by p.s.w.g, you might consider using modules to partition the scope.
I would say that, in F#, having two records with the same labels in the same namespace is a bit of a code smell.