2011-08-09 53 views
0

創建一個包含從F#拋出的類型的異常的最佳方式是什麼?以下不起作用:如何定義異常類型和另一種類型之間的遞歸關係?

// this fails since HeaderInfo is not yet defined. Can't seem use the and-keyword 
// on HeaderInfo 
exception MissingHeader of string*HeaderInfo 

type HeaderInfo = 
    { 
     DefaultHeaderIndices: Map<string, int>; 
     AdditionalStudyIndices: Map<string, int>; 
     VolumeIndex: int option; 
    } 
    with member this.GetCommonIndex(name) = 
      match this.DefaultHeaderIndices.TryFind(name) with 
      | Some(idx) -> idx 
      | None -> 
       match this.AdditionalStudyIndices.TryFind(name) with 
       | Some(idx) -> idx 
       | None -> 
        match this.VolumeIndex with 
        | Some(idx) when name = optionalHeader -> idx 
        | _ -> raise <| MissingHeader(name, this) 

謝謝!

回答

6

您可以使用類型的擴展將成員添加到之前聲明的類型。當你在同一模塊中使用類型擴展時,該成員被編譯爲該類型的普通(實例)成員,因此它意味着與普通成員完全相同。

這樣,您可以先聲明HeaderInfo,然後聲明missingHeader,然後將成員GetCommonIndex添加到HeaderInfo類型。

編輯:我想你也可以使代碼更好一點使用主動模式(儘管這是一個稍微巧妙運用)

type HeaderInfo = 
    { DefaultHeaderIndices: Map<string, int> 
     AdditionalStudyIndices: Map<string, int> 
     VolumeIndex: int option } 

exception MissingHeader of string*HeaderInfo 

let (|TryFind|_|) map key() = Map.tryFind key map 

type HeaderInfo with 
    member this.GetCommonIndex(name) = 
     match(), this.VolumeIndex with 
     | TryFind this.DefaultHeaderIndices name (idx), _ 
     | TryFind this.AdditionalStudyIndices name (idx), _ -> idx 
     | _, Some(idx) when name = optionalHeader -> idx 
     | _ -> raise <| MissingHeader(name, this) 
+0

謝謝,完美的作品 – Rickard

5

托馬斯的回答是罰款。另一種選擇是不使用

exception Foo ... 

,而使用

type Foo() = 
    inherit System.Exception() ... 

and OtherRecursiveType ... 

也就是說,申報使用正常類形態異常,然後用type...and...遞歸的type選自S。

相關問題