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.
Given this foo.fs:
#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())));;
Run 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) #