问题
I want a list of Reports. Report can be either Detail or Section types.
module Data
type Section = { Header: string;
Lines: string list;
Total: string }
type Detail = { State: string;
Divisions: string list;
Sections: Section list }
type Summary = { State: string;
Office: string;
Sections: Section list }
type Report = Detail | Summary
Then in my code, I'd like to do the following:
let mutable (reports:Report list) = []
...
reports <- detail::reports
// or
reports <- summary::reports
The compiler complains in the first case: "The expression was expected to have type Report but here has type Detail", and appropriately similarly in the second case.
Am I out of my mind for wanting to do such a thing? Should I be thinking about the problem differently? Because Report is either Detail or Summary, shouldn't a list of Report accept either a Detail or a Summary? What is a Report list if not a list of Detail or Summary?
Thanks.
回答1:
You've just got your syntax a bit wrong:
type Report = Detail of Detail | Summary of Summary
reports <- (Detail detail)::reports
// or
reports <- (Summary summary)::reports
In your code you've basically just defined the Report
type to be an enum with the two possible values Details
or Summary
(these are like labels, not the types of different subtypes in this context). Discriminated unions in F# are explicitly tagged, so you've also got to use one of the union constructors to create an instance to put into the list.
回答2:
You need to change your Report
type to:
type Report = Detail of Detail | Summary of Summary
since your current definition just names the two cases of your Report type, and these names are not related to the existing Detail
and Summary
types.
You can then filter the Detail
and Summary
elements using List.choose
e.g.
let details = reports |> List.choose (function Detail(d) -> Some(d) | _ -> None)
来源:https://stackoverflow.com/questions/13770911/f-list-of-union-types