The definition of the selection type is as follows
type Choice<'a, 'b> = | Choice1Of2 of 'a | Choice2Of2 of 'b
Therefore, when you create an instance of type Choice, as you do in choice4 , you use only one of these legs, this essentially leaves a hole (the type that describes 'b ) that the debugger should fill, in fact, it even you cannot be sure that the type is actually Choice<'a,'b> , so you will get some temporary type that is represented by FSharpFunc. Similarly, a type inference engine will tell Choice<string, 'a> , where 'a represents the hole until the instance is matched, and then forces you to enter the other side. Providing a type signature in a string, e.g.
let choice4 : Choice<string, bool> = Choice1Of2 "test"
means that you fill the hole and provide the debugger with enough information to properly represent the type.
EDIT (see comments): choice3 is represented as Choice1Of2<string,obj> , because obj is considered Top (the most common type). This is the type return type output that is used when it has exhausted all other parameters. If we add some code, for example.
let result = match choice3 with | Choice1Of2 t -> t.GetHashCode() | Choice2Of2 t -> t
then we get Choice<string, int> , since the type of GetHashCode() is int , so the result of the second match clause must be int for the type of result so that the expression is consistent.
source share