Trying to understand the type of choice in F #

I tried to understand the code in a Scott Ulashin RoP article:

http://fsharpforfunandprofit.com/posts/railway-oriented-programming-carbonated/

It uses the types Choice1Of2 and Choice2Of2 in F #. I was trying to figure out how to use these things by debugging them when I came across the following scenario:

module TestModule open Microsoft.VisualStudio.TestTools.UnitTesting // generic union type (like Choice1Of2, I think) type Things<'a> = | Thing of 'a // explicit union type (for comparison) type Numbers = | Integer of int [<TestClass>] type Tests() = // method to make a Choice1Of2 (from the article) let makeChoice (a : string) : Choice<string, 'a> = Choice1Of2 a [<TestMethod>] member public this.WhyYouNoHaveItemValueAndStuff() = let choice1 = Thing "test" // debug = Thing "this" let choice2 = Integer 3 // debug = Integer 3 let choice3 = makeChoice "test" // debug = Choice1Of2 w/Item = "test" let choice4 = Choice1Of2 "test" // debug = Tests.choice4@24 ??? // bogus test stuff below here let choices = (choice1, choice2, choice3, choice4) Assert.IsNotNull(choices) 

Why, when I do Choice1Of2 directly (choice4), do I not get the same debugging result as choice 3. Why is using the method for choice 3 necessary to get the same result as for choice1 and 2?

EDIT:

Choice4 seems to change to this:

 let choice4 : Choice<string, Object> = Choice1Of2 "test" 

works. I just don’t understand why I need it. The right side of the assignment is as clear as the day, which type is set.

+6
source share
1 answer

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.

+5
source

Source: https://habr.com/ru/post/981464/


All Articles