2010-12-02 4 views
3

나는 쓰기를 시도하고 무엇 :F #에서 여러 제약 조건을 만족하는 형식을 반환하는 제네릭 함수를 선언하는 방법?

type A() = 
    interface IX with ... 
    interface IY with ... 

type B() = 
    interface IX with ... 
    interface IY with ... 

let mk t : 'T when 'T :> IX and 'T :> IY = 
    match t with 
    | Choice1 -> new A() 
    | Choice2 -> new B() 

참고 MK의 반환 유형에 유형 제약. 그것은 컴파일하지 않지만 컴파일러는 A와 B를 'T'로 변환 할 수 없다는 불평을합니다.

+1

그냥 재미로 C# http://pastebin.com/daFFKTwB에서 해당 코드를 비교하십시오. 구체적인 유형의 'T'를 반환하려고하지만 나머지 함수에서 해당 유형을 사용하지 않습니다. 콘크리트 A 또는 B를 반환하려고 시도하며 형식 검사기는 당신은 정말로 의도했습니다. – Juliet

+0

추가 고려 사항 :'let x, y = mk Choice1, mk Choice2'라고 쓰면'x'와'y'에는 어떤 타입이 있습니까? – Juliet

+0

맞아, 나는 "A is a T"와 "B is-a T"라고 생각하고 있었지만,이 문장들이 독립적으로 고려 될 때만 정확하다. Tomas의 해법은 두 경우 모두 T가 동일하다는 요구를 완화하고 kvb의 해는 두 경우를 모두 만족시키는 새로운 유형 T를 도입합니다. – Joh

답변

7

제약 조건은 괜찮지 만 제약 조건을 만족하는 유형이없고 AB의 상위 유형이되는 문제가 있습니다.

구조체는 두 가지 모두에서 동일한 유형을 반환해야하므로 두 가지 분기에 대해 변환이 작동하도록 일부 형식에 업 캐스팅 (:>)을 추가해야합니다. 유형은 IX 또는 IY 일 수 있지만 제약 조건을 충족시키지 못합니다.

.NET이 사용자가 IX+IY과 같은 것을 쓸 수있는 경우에만 가능합니다. 이는 두 인터페이스를 모두 구현하는 유형을 의미합니다. 그럼 당신은 내가 최선의 해결책은 단순히 튜플 두 번 같은 인스턴스를 포함 IX * IY을 반환하는 것입니다 생각이 유형 예컨대 :

let (a:IX+IY) = new A() // This isn't supported 

의 값으로 작업 할 수 있지만, 서로 다른 유형을 나타내는 것입니다. 여기에 당신이 쓴 constriant 매우 유용 할 수 있습니다 :

// Type: 'a -> IX * IY when 'a :> IX and 'a :> IY 
let asTuple a = (a :> IX, a :> IY) 

let mk t = 
    match t with 
    | Choice1Of2() -> new A() |> asTuple 
    | Choice2Of2() -> new B() |> asTuple 
7

당신이 유형 AB를 제어 할 경우, 가장 간단한 해결책은

type IXY = 
    inherit IX 
    inherit IY 

을 정의하고 AB 상속 IXY을 가지고, 그리고 것 mk은 제네릭 형식이 아닌 IXY을 반환합니다 (어쨌든 제약 없이도 실제로는 이해가되지 않습니다).

+0

나는 kvb에 동의한다. 이것은 이것에 대한 가장 일반적인 접근법이다. – Alex

관련 문제