问题
My code is below. I am writing code to group by and then average another row, which is what I have down below. But instead of passing the whole function everytime, I want to be able to just pass in the CSV or data as the function parameter in one line and do this for multiple times for different data sets. As you can see from "row.income" and ".Rows" I am using a TYPE, but when I try to call the function later with a TYPE, it gives me an error. How would I go about doing this?
FYI the errors are that the rows do not exist because I am using "values" as a parameter and not the actual CSV file, because I call that later. This is the error I need to fix, to be able to call a specific row in the function, while passing a type as the parameter.
// When I try to call the function with Type
type Csvdata = CsvProvider<somefile>
state Csvdata
// This results in an error
回答1:
You cannot pass a type as a parameter in the way you describe. You can pass a generic type parameter, but to do what you want, the syntax will be a little different, because you'll need to use Statically Resolved Type Parameters on an inline function. Using the example csv.txt
with the following data:
name,income
bob,134.56
mary,350.13
The implementation would look like this:
let inline state< ^t, ^a, ^b when ^t: (static member GetSample: unit -> ^a)
and ^a: (member Rows: ^b seq)
and ^b: (member Income: decimal) > () =
let sample = (^t: (static member GetSample: unit -> ^a) ())
let rows = (^a: (member Rows: ^b seq) sample)
rows |> Seq.averageBy (fun row -> (^b: (member Income: decimal) row))
type Csvdata = CsvProvider<"csv.txt", HasHeaders = true>
state<Csvdata, CsvProvider<"csv.txt">, Csvdata.Row> ()
Here, ^t
is the specific type of the provider for your file, in this case Csvdata
, but which we are only requiring to have a method called GetSample
that returns another type, ^a
. ^a
is the type of the type provider itself, in this case, CsvProvider<"csv.txt">
, but which we are only requiring to have a property called Rows
that gives us a sequence of some type ^b
. Finally, ^b
represents the type of each row, in this case Csvdata.Row
, but which we are only requiring to have a decimal
property called Income
.
By using the type constraints in this way, you can pass any combination of types that meet the constraints, so it will work for any CsvProvider
for any CSV file that has an Income
column.
Running the code for our sample file gives the following output:
val it : decimal = 242.345M
来源:https://stackoverflow.com/questions/50765832/how-to-pass-a-type-as-a-function-parameter-in-f