此问题是对早期问题Preserving Field names across the F#/C# boundary
的跟进由于F#类型提供程序遇到当前的限制(请参阅前面的问题),我想将类型提供程序生成的列表映射到我自己的记录列表,其中记录部分是
type inspection = {
inspectionID : string;
inspectorID : int;
EstablishmentID : string;
EstablishmentName : string; // other members elided
}
我认为这样做的方法是使用Seq.map,但我不确定。 (回想一下,我正在做一个学习练习。)所以这就是我的尝试:
type restaurantCsv = CsvProvider<"C:\somepath\RestaurantRatings2013.csv",HasHeaders=true>
// which generates a type, but it is an "erased" type, so member names do not propogate
// over to C#.
type RawInspectionData(filename : string) =
member this.allData = restaurantCsv.Load(filename) // works fine
member this.allInspections =
this.allData.Data
|> Seq.map(fun rcrd -> new inspection[{inspectionID = rcrd.InspectionID;}])
当然,完整的声明将其他成员名称作为检查的一部分,这里为了简洁而省略。有人向我指出 F#科学家的第43页,这就是为什么我认为这种格式与花括号一起使用。但是这会产生语法错误,“表达式中的意外符号'{'。预期',',']'或其他标记。”
但是,希望这个片段足以显示我想要做的事情,从Erased Type创建Generated Type。我怎么能做到这一点?
答案 0 :(得分:3)
您的代码正朝着正确的方向发展。使用Seq.map
(类似于LINQ中的Select
)时,需要将原始序列的单个元素转换为新序列的单个元素。因此lambda函数只需要创建一个记录实例。
使用{ Field1 = value1; Field2 = value2; ... }
构建记录,因此您需要:
type RawInspectionData(filename : string) =
let allData = restaurantCsv.Load(filename) // works fine
member this.allInspections =
allData.Data
|> Seq.map(fun rcrd -> {inspectionID = rcrd.InspectionID})
我还将allData
从成员更改为本地let
定义(这使其成为类的私有字段)。我想你的原始代码new inspection[{...}]
试图用元素创建一个单独的数组 - 创建一个你要编写的数组[| { Field = value; ... } |]
(并且编译器会为你推断出数组的类型)。但在这种情况下,不需要任何数组。