如何定义异常类型和另一种类型之间的递归关系?

时间:2011-08-09 17:25:44

标签: exception f#

创建包含从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)

谢谢!

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分:5)

托马斯的回答很好。另一种选择是不使用

exception Foo ...

而是使用

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

and OtherRecursiveType ...

即,使用普通的类表单声明异常,然后使用type...and...type s之间进行递归。