函数不能将静态参数的值作为参数,因为该值必须在编译时确定。这意味着如果你写:
let [<Literal>] sample = """{"name":"Peter","age":9}"""
let parseHtml html = JsonProvider<sample>.Parse(html)
...一切都很好,因为编译器知道这sample
是一个常量(并且编译器知道它的值),因此它可以实例化类型提供程序(在编译期间)以生成类型。如果你写这样的东西:
let parseHtml sample html = JsonProvider<sample>.Parse(html)
...然后编译器无法知道sample
运行时的值可能是什么,因此它无法在编译时生成所需的类型。类型提供程序在运行时不“存在”,因此无法动态生成类型(这不会真正有用,因为类型提供程序的目的是为您提供一些编译时安全保证)。
你的榜样。JsonProvider<sample>.Parse
在您的情况下,将特定函数作为参数可能是有意义的:
let SyncIt url parse storer =
async {
url
|> MakeRequestAsync
|> Async.RunSynchronously
|> parse
|> Seq.iter (converter >> storer)
}
这样,调用者可以将静态参数指定给类型提供程序,然后调用您的函数进行同步:
let [<Literal>] sample = """{"name":"Peter","age":9}"""
SyncIt url (JsonProvider<sample>.Parse) storer
虽然,我并不完全清楚为什么在这里需要类型提供程序。提供者的目的是为您提供可用于访问具体数据源的好类型。如果您使用任何converter
JSON 数据文件,那么您可能只使用JSON 解析器(也在 F# Data 中)来完成工作。storer
异步块。另外,请注意,您的代码并没有真正异步运行 - 要使其异步,您需要使用let!
以下操作下载 URL:
let SyncIt url parser storer =
async {
let wc = new WebClient()
let! html = wc.AsyncDownloadString(url)
parser html
|> Seq.iter (converter >> storer)
}