2016-12-16 2 views
1

디버깅을 위해 printfn "%A"이 제공하는 모든 부동 소수점에 대한 자세한 정보가 필요하며 모든 테스트 코드가 일반화되어 있습니다. 그래서 나는 box을 알아 냈고 의미있는 출력을 얻기 위해 유형을 매치했습니다.하나 인 경우 해당 일반 식별 형 유니온에 일반화 된 유형 캐스팅

그러나 유형은 옵션 유형 또는 Result<_, _> 유형 (성공/실패) 일 수 있습니다. 이러한 유형은 패턴 일치 당신이 차별 노조로 처리,하지만 난 경우가 충돌하지 않습니다를 입력-테스트 :

// Illustrative example of what I'm trying to achieve (I think) 
let rec mkStr v = 
    match box v with 
    | :? double as dbl -> Str.fromFloat dbl 
    | :? int64 as i -> i.ToString() 
    | _ -> 
     match v :> obj with 
     | :? Result<_, _> as res -> // this will never succeed 
      match res with 
      | Success s -> mkStr s 
      | Fail _ -> "Fail" 
     | x -> 
      x.ToString() 

나는, 위의 권투/언 박싱/주조의 다양한 시도했습니다 이러한 종류 중 하나입니다. 내가 디버그 할 때 명확하게 Success이 통과한다는 것을 볼 수 있습니다. 디버거는 Result을 표시하지 않습니다. DU의 각 판별자가 그 자체로 하나의 유형이라는 것을 알고 있으므로 어떤 일이 일어나는지 알지만 컴파일러에게 또는 Fail 중 하나와 일치하면 DU로 취급하도록 컴파일러에 지시 할 수 있습니까?

TLDR : 일반화 된 유형이있는 경우 유형이있을 경우 기본 DU에 테스트하고 캐스트 할 수 있습니까?

(PS :이 일반적으로 뒤의에 대해 이동하는 방법이 아니라는 것을 알지만 printf "%A"이 존재하는 것처럼, 나는이 상황에서로, 때때로이 필요하다고 가정)받을 인용을 사용

+3

http://stackoverflow.com/q/3151099/82959, http://stackoverflow.com/q/39875110/82959 및 http://stackoverflow.com/q/2140079/82959를 참조하십시오. – kvb

+0

@kvb, 나는 이미 재선이 필요하다고 두려워했다. 능동적 인 패턴과 인용문으로 좋은 솔루션. 감사. 내가 Google에서 찾지 못한 이유를 모르겠습니다. – Abel

답변

3

솔루션을 @kvb가 주석에 게시 된 패턴 일치 지원은 좋은 트릭입니다. 과거에는 비슷한 문제가 있었고 약간 다른 트릭을 사용했습니다. 리플렉션을 사용하여 값을 해체하고 검사하는 대신 리플렉션을 사용하여 올바른 유형 인수로 일반 메소드를 호출 할 수 있습니다. Make은 우리가 정적으로 알 수없는 'T2에 대한 유형 option<'T2>입니다 값으로 호출

type MakeString = 
    static member Make<'T>(o:'T) = 
    match box o with 
    | :? float as f -> sprintf "Float: %A" f 
    | o -> 
     if typeof<'T>.Name = "FSharpOption`1" then 
      let tys = typeof<'T>.GetGenericArguments() 
      typeof<MakeString>.GetMethod("MakeOption") 
      .MakeGenericMethod(tys).Invoke(null, [| o |]) :?> string 
     else 
      failwith "Unknown" 

    static member MakeOption<'T>(o:option<'T>) = 
    match o with 
    | None -> "None" 
    | Some v -> "Some " + MakeString.Make(v) 

MakeString.Make(Some 3.14) 

, 우리는 제네릭 형식 인수를보고 반사를 사용하여 'T2를 찾은 다음 우리가 호출 : 여기에 최소한의 예입니다 을 'T2으로 형식 인수로 - MakeOption 안에 있으므로 옵션 안에 포함 된 값의 정적 유형을 알 수 있습니다.

정적 유형을 사용하여 모든 작업이 가능하므로 값이 null으로 표시 될 때 무료로 작동하므로 None.GetType()을 직접 호출하면 예외가 발생합니다. previous answer posted by @kvb도이 상황을 처리하지만 특별한 경우를 사용합니다.

+0

kvb가 'null'로 덮여있는 것처럼 보입니다. _ "null이 유효한 값 인 경우 특별한 경우 논리가 필요합니다 (예 : Option.None)"_. 이것은 좋은 해결책입니다. '\'1'은 일반적인 타입의 접미사입니까? – Abel

+1

_ (와우, 백틱을 백틱으로 바로 잡을 수 있다는 것을 몰랐다.) _ – Abel

+0

또한 F #이 DU 콘크리트 유형을 숨기지 않았기 때문에 문제가 제네릭으로 인한 것임을 강조하는 것처럼 보입니다. – Abel