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

Ric*_*ard 0 f# exception

创建包含从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)
Run Code Online (Sandbox Code Playgroud)

谢谢!

Tom*_*cek 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)
Run Code Online (Sandbox Code Playgroud)


Bri*_*ian 5

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

exception Foo ...
Run Code Online (Sandbox Code Playgroud)

而是使用

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

and OtherRecursiveType ...
Run Code Online (Sandbox Code Playgroud)

也就是说,使用普通的类表单声明异常,然后type...and...用于types 之间的递归.