F# - 该类型预计具有 Async<'a> 类型但有字符串 -> Asnyc<'a>反而

发布于 2024-10-29 08:10:31 字数 1788 浏览 1 评论 0 原文

在无耻地从 Tomas Petricek 的博客中窃取了一段代码片段之后: http://tomasp.net/blog/csharp-fsharp-async-intro.aspx 具体来说,这个(并对它进行了一些修改):

     let downloadPage(url:string) (postData:string) = async {
  let request = HttpWebRequest.Create(url)
// Asynchronously get response and dispose it when we're done
  use! response = request.AsyncGetResponse()
  use stream = response.GetResponseStream()
  let temp = new MemoryStream()
  let buffer = Array.zeroCreate 4096 

   // Loop that downloads page into a buffer (could use 'while' 
   // but recursion is more typical for functional language)
  let rec download() = async { 
   let! count = stream.AsyncRead(buffer, 0, buffer.Length)
   do! temp.AsyncWrite(buffer, 0, count)
   if count > 0 then return! download() }

   // Start the download asynchronously and handle results
  do! download()
  temp.Seek(0L, SeekOrigin.Begin) |> ignore
  let html = (new StreamReader(temp)).ReadToEnd()
  return html };;

我尝试用它执行以下操作,并在最后一行收到错误:

该类型预计具有 Async<'a> 类型,但具有 string ->改为 Asnyc<'a>

我在谷歌上搜索了该错误,但找不到任何可以揭示我的特定问题的内容。

let postData = "userid=" + userId + "&password=" + password + "&source=" + sourceId + "&version=" + version
let url = postUrlBase + "100/LogIn?" + postData
Async.RunSynchronously (downloadPage(url, postData));;

另外,我将如何修改代码,以便它异步下载非结束字节流(但在每个字节突发之间偶尔暂停)而不是字符串?当这个字节流通过时,我将如何集成读取它?我意识到这不仅仅是一个问题,但由于它们都密切相关,我认为一个问题会节省一些时间。

预先感谢,

鲍勃

P.S.由于我对 F# 还很陌生,请随时对我的代码进行任何更改/建议,以展示其如何以更实用的风格完成。我真的很想摆脱我的 C# 心态,所以我很感谢任何人希望分享的任何建议。

编辑:我不小心粘贴了我正在使用的错误片段。我确实对托马斯的片段进行了修改,但后来忘记了。

After shamelessly pilfering a code snippet from Tomas Petricek's Blog:
http://tomasp.net/blog/csharp-fsharp-async-intro.aspx
Specifically, this one (and making a few alterations to it):

     let downloadPage(url:string) (postData:string) = async {
  let request = HttpWebRequest.Create(url)
// Asynchronously get response and dispose it when we're done
  use! response = request.AsyncGetResponse()
  use stream = response.GetResponseStream()
  let temp = new MemoryStream()
  let buffer = Array.zeroCreate 4096 

   // Loop that downloads page into a buffer (could use 'while' 
   // but recursion is more typical for functional language)
  let rec download() = async { 
   let! count = stream.AsyncRead(buffer, 0, buffer.Length)
   do! temp.AsyncWrite(buffer, 0, count)
   if count > 0 then return! download() }

   // Start the download asynchronously and handle results
  do! download()
  temp.Seek(0L, SeekOrigin.Begin) |> ignore
  let html = (new StreamReader(temp)).ReadToEnd()
  return html };;

I tried to do the following with it, and got the error on the last line:

The type was expected to have type Async<'a> but has string -> Asnyc<'a> instead

I googled the error but couldn't find anything that revealed my particular issue.

let postData = "userid=" + userId + "&password=" + password + "&source=" + sourceId + "&version=" + version
let url = postUrlBase + "100/LogIn?" + postData
Async.RunSynchronously (downloadPage(url, postData));;

Also, how would I modify the code so that it downloads a non-ending byte stream (but with occasional pauses between each burst of bytes) asynchronously instead of a string? How would I integrate reading this byte stream as it comes through? I realize this is more than one question, but since they are are all closely related I figured one question would save some time.

Thanks in advance,

Bob

P.S. As I am still new to F# please feel free to make any alterations/suggestions to my code which shows how its done in a more functional style. I'm really trying to get out of my C# mindset, so I appreciate any pointers anyone may wish to share.

Edit: I accidentally pasted in the wrong snippet I was using. I did make an alteration to Tomas' snippet and forgot about it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

鲜肉鲜肉永远不皱 2024-11-05 08:10:31

当我尝试运行您的代码时,downloadPage(url, postData) 不起作用,因为 downloadPage 需要两个单独的字符串。 downloadPage url postData 是预期的。

如果您将 let 绑定更改为元组形式,或者 let downloadPage(url:string, postData:string) 您的调用也会正常工作。

要解释为什么会出现错误则更为复杂。柯里化形式创建一个返回函数或字符串 -> 的函数。字符串 ->在您的情况下为 Async 。因此,编译器看到您传递了一个参数(元组毕竟是单个项目),并看到结果必须是一个 string -> AsyncAsync 不兼容。它可能发现的另一个错误(在我的例子中确实如此)是 string * stringstring 不兼容。确切的错误是预期的字符串但发现'a * 'b

When I attempt to run your code downloadPage(url, postData) doesn't work as downloadPage expects two seperate strings. downloadPage url postData is what is expected.

If you changed the let binding to tuple form, or let downloadPage(url:string, postData:string) your call would have worked as well.

To explain why you got the error you got is more complicated. Curried form creates a function that returns a function or string -> string -> Async<string> in your case. The compiler therefore saw you passing a single parameter (tuples are single items after all) and saw that the result would have to be a string -> Async<string> which is not compatible with Async<string>. Another error it could have found (and did in my case) is that string * string is not compatible with string. The exact error being Expected string but found 'a * 'b.

余生共白头 2024-11-05 08:10:31

这就是我所拥有的:

Async.RunSynchronously (downloadPage(url, postData));;

这是持续随机猜测后有效的:

Async.RunSynchronously (downloadPage url postData);;

虽然,我不确定为什么这个更改解决了问题。想法?

This is what I had:

Async.RunSynchronously (downloadPage(url, postData));;

this is what worked after continued random guessing:

Async.RunSynchronously (downloadPage url postData);;

Although, I'm not sure why this change fixed the problem. Thoughts?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文