开发者

How to define a recursive relation between an exception type and another type?

What is the best way to create an exception that contains a type it is thrown from in F#? The following does not work:

// 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.GetCommonInde开发者_如何学Cx(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)

Thanks!


You can use type extensions to add members to a type that was declared earlier. When you use type extension within the same module, the member is compiled as an ordinary (instance) member of the type, so it means exactly the same thing as ordinary member.

This way, you can first declare HeaderInfo, then declare missingHeader and then add the member GetCommonIndex to the HeaderInfo type.

EDIT: I think you can also make the code a bit nicer using active patterns (although it is a slightly subtle use)

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)


Tomas' answer is fine. Another option is to not use

exception Foo ...

and instead use

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

and OtherRecursiveType ...

That is, declare the exception using the normal class form, and then use type...and... for recursion among the types.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜