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 type
s.
精彩评论