使用F# TypeProvider类型(例如FSharp.Data.JsonProvider<...>.DomainTypes.Url)的类型注释

7
我正在使用 FSharp.Data.JsonProvider 来读取 Twitter 推文。
通过尝试以下示例代码 https://github.com/tpetricek/Documents/tree/master/Samples/Twitter.API 我想要扩展推文中的 URL。
let expandUrl (txt:string) (url:Search.DomainTypes<...>.DomainTypes.Url) = 
    txt.Replace( url.Url, url.ExpandedUrl )

这将导致错误:
Lookup on object of indeterminate type based on information prior to this program point. 
A type annotation may be needed prior to this program point to constrain the type of the object.

我的问题是如何为上述 expandUrl 函数中的 URL 定义 TypeProvider 类型?
类型推断显示了以下结果。
val urls : FSharp.Data.JsonProvider<...>.DomainTypes.Url []

但是这在类型声明中是不被接受的。我认为"<...>"不是F#语法。

如何对使用TypeProvider类型进行类型注释,例如FSharp.Data.JsonProvider<...>.DomainTypes.Url

以下是完整的代码片段:

open TwitterAPI // github.com/tpetricek/Documents/tree/master/Samples/Twitter.API 
let twitter = TwitterAPI.TwitterContext( _consumerKey, _consumerSecret, _accessToken, _accessTokenSecret )
let query = "water"
let ts = Twitter.Search.Tweets(twitter, Utils.urlEncode query, count=100)

let ret = 
  [ for x in ts.Statuses do
      // val urls : FSharp.Data.JsonProvider<...>.DomainTypes.Url []
      let urls = x.Entities.Urls 
      // fully declarated to help the type inference at expandUrl
      let replace (txt:string) (oldValue:string) (newValue:string) = 
          txt.Replace( oldValue, newValue)
      // Error:
      // Lookup on object of indeterminate type based on information prior to this program point. 
      // A type annotation may be needed prior to this program point to constrain the type of the object. 
      // This may allow the lookup to be resolved.
      let expandUrl (txt:string) (url:FSharp.Data.JsonProvider<_>.DomainTypes.Url) = 
          replace txt url.Url url.ExpandedUrl
      let textWithExpandedUrls = Array.fold expandUrl x.Text urls
      yield textWithExpandedUrls
  ]

是的,<...> 不是 F# 语法,对于泛型类型,F# 使用下划线 <_>,但我认为这不适用于此处。你能发布一部分你正在尝试解析的 JSON 吗? - Phillip Trelford
我已经尝试过了。然后 _ 和 url.Url url.ExpandedUrl 就会出现红色波浪线。在 FSharp.Data.JsonProvider 之后也不可能通过“点浏览”来深入了解类型。 - user3114224
我将链接 https://github.com/tpetricek/Documents/tree/master/Samples/Twitter.API 添加到我正在处理的代码问题中。 - user3114224
我还在问题中添加了完整的代码片段。 - user3114224
2个回答

4
当您调用Twitter.Search.Tweetshttps://github.com/tpetricek/Documents/blob/master/Samples/Twitter.API/Twitter.fs#L284)时,返回类型是TwitterTypes.SearchTweets的一个领域类型之一,该类型是JsonProvider<"references\\search_tweets.json">的类型别名(https://github.com/tpetricek/Documents/blob/master/Samples/Twitter.API/Twitter.fs#L183)。
尽管在工具提示中它显示为 JsonProvider<...>.DomainTypes.Url,但您必须使用类型别名TwitterTypes.SearchTweets.DomainTypes.Url

谢谢,可以了!为什么类型推断不能显示正确的工具提示?还是我漏掉了什么。 - user3114224
是的,这可能是可以改进的东西。 - Gustavo Guerra

0

我遇到了一个类似的问题,试图弄清楚如何使用FSharp.Data HtmlProvider

我正在使用维基百科获取有关美国总统的信息。 HtmlProvider很好地发现了该网页中的各种表格,但我想将“总统数据”的处理逻辑提取为一个名为processRow的单独函数。

问题在于如何确定processRow函数的参数row的类型是什么。以下代码可以解决这个问题:

#load "Scripts\load-references.fsx"

open FSharp.Data

let presidents = new HtmlProvider<"https://en.wikipedia.org/wiki/List_of_Presidents_of_the_United_States">()

let ps = presidents.Tables.``List of presidents``

ps.Headers |> Option.map (fun hs -> for h in hs do printf "%s " h)

printfn ""

type Presidents = ``HtmlProvider,Sample="https://en.wikipedia.org/wiki/List_of_Presidents_of_the_United_States"``.ListOfPresidents

let processRow (row:Presidents.Row) =
  printfn "%d %s" row.``№`` row.President2

ps.Rows |> Seq.iter processRow

我没有为Presidents键入长类型别名,而是使用Visual Studio自动完成功能猜测List of presidents的类型可以从以Html开头的某些内容中发现,结果成功了,并且包含了四个单反引号。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接