How to pass a type as a function parameter in F#?

◇◆丶佛笑我妖孽 提交于 2019-12-13 04:23:29

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!