2013-02-27 6 views
7

내가 열거에 문자열에서 일반 변환 연산자를 정의하기 위해 노력하고있어, 나는이처럼 사용하고 싶습니다 :F # 형 제약

:

let day = asEnum<DayOfWeek>("Monday") 

을하지만이 구현

let asEnum<'a, 'b when 'a: (new : unit -> 'a) and 'a : struct and 'a :> ValueType and 'a : enum<'b>> text = 
    match Enum.TryParse<'a>(text) with 
    | true, value -> Some value 
    | false, _ -> None 

난 단지 다음과 같이 사용할 수 있습니다 :

let day = asEnum<DayOfWeek,_>("Monday") 

나이 :

let day:DayOfWeek option = asEnum("Monday") 

나는 형 제약에서 전부 'a : enum<'b>를 생략하면 내가 원하는대로, 내가 가질 수 있지만, 누군가가 유형을 지정하지 않는 다음 경우는 정말 좋아하지 않는, int로 기본 설정됩니다, I 제약 조건을 지정할 때처럼 컴파일 시간 오류를 내기를 원합니다.

하나의 유형 매개 변수를 지정하고 다른 하나를 유추하는 트릭이있을 수 있습니까? 어떤 아이디어?

답변

2

불행하게도, 당신이 모든 것을 밖으로 철자해야 할 것 같다 제약 증대하기 위해 : (KVB가 지적했듯이, 당신은 꺾쇠 괄호 밖에서 'T : enum<int> 제약 조건을 추가하여 TryParse에 대한 제약을 중복되지 않도록 할 수 있습니다)

이것은 또한 작동합니다

: 기본 유형 int없는 경우이 컴파일 타임 오류를 제공

let asEnum<'T 
    when 'T : enum<int> 
    and 'T : struct 
    and 'T :> ValueType 
    and 'T : (new : unit -> 'T)> text = 
    match Enum.TryParse<'T>(text) with 
    | true, value -> Some value 
    | _ -> None 

3

어때?

type AsEnum = 

    static member Get<'a, 'b when 'a: (new : unit -> 'a) and 'a : struct and 'a :> ValueType and 'a : enum<int>> (text:string) = 

     match Enum.TryParse<'a>(text) with 
     | true, value -> Some value 
     | _ -> None 

    static member Get<'a, 'b when 'a: (new : unit -> 'a) and 'a : struct and 'a :> ValueType and 'a : enum<int64>> (text:string) = 

     match Enum.TryParse<'a>(text) with 
     | true, value -> Some value 
     | _ -> None 

let a = AsEnum.Get<BindingFlags>.Get "DeclaredOnly" 

내가 전화를 오버로드하는 추론 할 수있는 컴파일러를 얻을 수 있는지 확인하려고하지만, 경우는 모호한 오류

+0

어머나. 나는 그것이 유효한 구문인지조차 몰랐다. 나는 당신이''a : enum ''으로 변경하면 그가 원하는 것을 줄 것이라고 생각합니다. 또한 경고를 피하기 위해'let e : System.Reflection.BindingFlags option = asEnum "DeclaredOnly"를 할 수 있습니다. – Daniel

+0

왜이 기능이 작동하지만 '<' '>'사이에 동일한 제약 조건을 두지 않습니까? – Daniel

+0

@Daniel - @ovastus가'int'를 강요하기를 원하지 않는다고 생각합니다. 가능한 경우 추측 할 수 있기를 바랍니다. – kvb

0

내가 시도 또 다른 것은이 있었다 3 년 후 조금 업데이트 됨^_^

이 문자열 확장을 사용하여 문자열을 열거 형으로 변환

type System.String with 
     /// Strongly-typed shortcut for Enum.TryParse(). 
     member this.ToEnum<'a when 'a :> System.Enum and 'a : struct and 'a : (new: unit -> 'a)>() = 
      let ok, v = System.Enum.TryParse<'a>(this, true) 
      if ok then Some v else None  

enum 선언에주의하십시오.

type failingEnum = 
      | FirstValue 
      | SecondValue 
      | AnotherValue 

type compliantEnum = 
      | FirstValue = 0 
      | SecondValue = 1 
      | AnotherValue = 2 

그런

let x = "whatever".ToEnum<failingEnum>(); 
//- will give error failingEnum is not compatible with the type System.Enum 

let x = "whatever".ToEnum<compliantEnum>(); 
//- will succeed ! 
0

A를 실패

let asEnum s :'a option when 'a:enum<'b> = 
    match System.Enum.TryParse s with 
    | true, v -> Some v 
    | _ -> None 

// works, but warns that type params shouldn't be given explicitly 
asEnum<System.Reflection.BindingFlags,_> "DeclaredOnly"  
// also okay 
(asEnum "DeclaredOnly" : System.Reflection.BindingFlags option) 
+1

기술적으로'failingEnum'은 열거 형이 아닌 공용체 유형입니다. 그것이 실패하는 이유입니다. – CaringDev

+0

물론 ... 댓글을 주셔서 감사합니다. 그래서 내가 그것에 주석을 추가 한 이유는 enum을 종종 union으로 정의하기 때문입니다. 나는 그렇게 오래 전에 그 사람들의 일부였다 :) –