2015-01-23 3 views
6

F 번호의 선택 유형 이해하려고 노력 :내가 스콧 Wlaschin로의 ROP 문서의 코드를 이해하는 데 어려움을 겪고 있었어요

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

그는 F 번호에 Choice1Of2 & Choice2Of2 유형을 사용합니다을. 그렇게하지, 내가 직접 Choice1Of2 (choice4)를 할 때 왜 그

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 = [email protected] ??? 

     // bogus test stuff below here 
     let choices = (choice1, choice2, choice3, choice4) 
     Assert.IsNotNull(choices) 

입니다 : 본인은 다음과 같은 시나리오를 가로 질러 왔을 때, 그들을 디버깅하여 이러한 일을 활용하는 방법과 타협하려고했다 선택 3과 동일한 디버깅 결과를 얻습니다. 왜 choice1을 선택 2와 같은 종류의 결과를 얻는 데 필요한 방법을 사용합니까? & 2?

편집 :

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

그것을 밖으로 작동합니다

이에 choice4를 변경하는 것으로 보인다. 왜 저에게 필요한지는 완전히 분명하지 않습니다. 과제의 오른쪽은 어떤 유형이 설정되는지에 대한 명확한 정보입니다.

+1

정확히 어떤 유형의 추론이 거기에서하고 있는지 확실하지 않지만이 값의 정의되지 않은 유형에 혼동을 일으킬 수 있습니다. 실행 시간 타입은 두 가지 모두'Choice '이며, 사용법은 동일합니다. 'choice03'과'choice4'에': Choice '과 같은 타입 주석을 사용하면 디버그 정보에서도 똑같이 보입니다. – Vandroiy

+0

응답을 위해 @Vandroiy Thx. 그것은 실제로 올바른 행동을 강요합니다. 아직도 이상해야합니다. – TBone

+2

이것은 올바른 행동에 관한 것이 아니라 디버거에서 관찰하는 것에 관한 것입니다.내 생각 엔 당신이보고있는 것은 choice4가 불완전하게 추론 된 유형을 가지고 있으며 불완전하게 추론 된 유형의 내부 표현이 일반 매개 변수가있는 유형의 표현과 다르다는 것입니다. 이러한 바인딩이 평가되거나 (디버거와 달리) 코드에서 형식 검사가 다르게 나타나는 경우를 제외하고는 VS 구현 세부 사항 이상은 아닙니다. –

답변

5

당신은이 다리 중 하나를 사용 choice4에서와이 본질적으로 구멍을 잎의 선택 유형의 인스턴스를 생성 할 때

type Choice<'a, 'b> = 
     | Choice1Of2 of 'a 
     | Choice2Of2 of 'b 

그래서 다음과 같이 선택 유형의 정의는합니다 (디버거가 채워야 만하는 타입을 가리키는 타입 ('b)은 실제로 런타임에 타입이 실제로 Choice<'a,'b>이라는 것을 확신 할 수 없으므로 FSharpFunc로 표현되는 임시 타입을 얻을 수 있습니다. 같은 방식으로 타입 추론 메커니즘이 Choice<string, 'a>이라고보고합니다. 'a은 인스턴스가 일치 할 때까지 구멍을 나타냅니다. 그러면 인스턴스가 일치되어 다른 쪽을 입력해야합니다. 예 : 인라인으로 유형 서명 제공.

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

구멍을 채우고 디버거에서 유형을 올바르게 나타내는 데 필요한 정보를 제공하고 있습니다.

EDIT (의견 참조) : choice3은 obj이 최상 (가장 일반적인 유형)으로 간주되기 때문에 Choice1Of2<string,obj>으로 표시됩니다. 이것은 다른 모든 옵션을 다 써 버렸을 때 사용되는 유형 추론 메커니즘 인 폴백 유형입니다. 예를 들어 몇 가지 코드를 추가하면 GetHashCode()의 종류에 따라서 표현이 일치하도록하자결과의 유형에 대한 int해야 두 번째 경기 절의 결과 int 같이

let result = 
    match choice3 with 
    | Choice1Of2 t -> t.GetHashCode() 
    | Choice2Of2 t -> t 

우리는 Choice<string, int>을 얻을 것이다.

+0

나는 그것이 전체적인 설명이라고 생각하지 않습니다. 문제는 "a"는 "구멍"을 나타냅니다. 그 대답은 컴파일러가 타입 매개 변수를보다 구체적으로 지정할 수있는 몇 가지 다른 정보를 접할 수 있는지를 기다리고 있으며 "채워지지 않은 구멍"과는 다른 표현을 가지고 있다는 것입니다. "채워지지 않을 구멍"때문입니다. –

+0

그러나 이미 Choice1Of2 "test"를 인스턴스화하여 문자열을 제한했습니다. 그래서 그것은 더 이상 구멍이 아닙니다. –

+0

다른''a''에 대해서'''에있는''a''에 대해서 말하고 있습니다. 그러나 이제는 VS에서이 코드를 얻었으므로'choice4'는 예상대로 ('Choice ') 입력되었고'choice3'는 약간 놀랍습니다. (나는 또한 F #에 익숙하지 않지만 OCaml과 작업했습니다.) 어떤 시점에서'choice3'의 두 번째 매개 변수가'obj'인지 결정하지 못했습니다. –