A feature or a bug?
An innocent-looking pair of parentheses ends up influencing the runtime representation of discriminated union types.
I would prefer not to have this. The two representations seem conceptually redundant, it would be better to just pick the faster one.
#light open Microsoft.FSharp.Reflection type A1 = A1 | B1 of (A1 * A1) type A2 = A2 | B2 of A2 * A2 printfn "%A" ((FSharpType.GetUnionCases(typeof<A1>) |> Array.map (fun x -> x.GetFields())));; printfn "%A" ((FSharpType.GetUnionCases(typeof<A2>) |> Array.map (fun x -> x.GetFields())));;
fsi --quiet --exec foo.fs to produce this:
[|[||]; [|Microsoft.FSharp.Core.Tuple`2[FSI_0001.Foo+A1,FSI_0001.Foo+A1] B11|]|] [|[||]; [|FSI_0001.Foo+A2 B21; FSI_0001.Foo+A2 B22|]|]
I found this code while testing a library that produced different results depending on the presence or absence of the parentheses.
Update: A feature! Thanks to Zedd. I should know my specs and my OCaml:
Objective Caml version 3.10.2 # type c = C of int * int;; type c = C of int * int # match C(1, 2) with | C x -> x;; The constructor C expects 2 argument(s), but is here applied to 1 argument(s) # type c = C of (int * int);; type c = C of (int * int) # match C(1, 2) with | C x -> x;; - : int * int = (1, 2) #