Sergi Mansilla
Sergi Mansilla

Reputation: 12803

How can I use a command line argument as the argument for a type provider?

What's the proper way to use a dynamic value as the argument for a type provider like CsvProvider? I'd expect this to work:

open System.IO
open FSharp.Data

[<EntryPoint>]
let main argv =
    type Stock = CsvProvider<argv.[0]>
    let stockData = Stock.Load(argv.[0])

    for row in stockData.Rows do
        printfn "(%A, %A, %A, %A)" row.High row.Low row.Open row.Close

    0 //Exit

What am I doing wrong?

Upvotes: 0

Views: 167

Answers (2)

Jwosty
Jwosty

Reputation: 3644

For any type provider you're going to need a schema so that the compiler can understand what the shape of your data looks like. Consequently it has to be something that's available at compile time. One way to do this is to put it in a file:

High,Low,Open,Close
29.53,29.17,29.45,29.23
29.70,29.40,29.61,29.50
29.65,29.07,29.07,29.56
29.57,29.18,29.47,29.34

Which you can then import outside of your main function like so:

// or whatever you called the file
type Stock = CsvProvider<"schema.csv">

CsvProvider also lets you just give it a schema inline if you prefer:

type Stock = CsvProvider<"High,Low,Open,Close
                          29.53,29.17,29.45,29.23">

Here it is in the context of the whole program:

open System.IO
open FSharp.Data

type Stock = CsvProvider<"schema.csv">


[<EntryPoint>]
let main argv =
    let stockData = Stock.Load(argv.[0])

    for row in stockData.Rows do
        printfn "(%A, %A, %A, %A)" row.High row.Low row.Open row.Close

    0

Upvotes: 0

Aaron M. Eshbach
Aaron M. Eshbach

Reputation: 6510

You can't use a command-line argument as the static argument for the type provider. The line type Stock = CsvProvider<argv.[0]> requires the parameter to CsvProvider to be a compile-time constant, because the types generated by the type provider are created a compile-time, not at run-time.

You can supply a different value to the Load function, and this can be a run-time value, as in your line Stock.Load(argv.[0]), but you will need to use a compile-time constant file name or sample data that matches the expected layout of the file being passed as a command-line argument, so that the types generated at compile-time will match the structure of the file being passed in at run-time (even though the data may be different).

Upvotes: 2

Related Questions