I am trying to use a specific member of a discriminated union as a parameter type. For example:
type SomeUnion =
| A of int * int
| B of string
type SomeType(A(i, j)) =
member this.I = i
member this.J = j
let a = A(10, 20)
let instance = SomeType(a)
but this is illegal syntax, and complains with "Unexpected symbol '(' in type definition" for SomeType's param list. This is valid syntax:
let doSomethingWithA (A(i, j)) = i + j
but the type signature is SomeUnion -> int
rather than A -> int
, and it complains about incomplete pattern match (understandable given the signature).
So is this possible? I believe in F# union members are compiled to CLR classes, so seems theoretically possible, but is it practically (i.e. without using something like reflection)? Otherwise I suppose you have to do the manual OOP way which is more verbose, and can't guarantee complete matches.
I agree that it is surprising that you cannot pattern match the constructor argument. It does work with normal members.
Maybe you can do an explicit match in the constructor, to get a runtime error if the value is wrong:
type SomeType(a) =
let i, j = match a with | A(k, l) -> k, l
member this.I = i
member this.J = j
But otherwise, one must understand that A
is not a type. So it is not surprising that the type of doSomethingWithA
is not as you expected. And you would have to live with the incomplete pattern match warnings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With