F # - ожидалось, что тип будет иметь тип Async <'a>, но вместо него будет строка -> Asnyc <' a> - PullRequest
1 голос
/ 04 апреля 2011

После бесстыдного воровства фрагмента кода из блога Томаса Петричека: 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));;

Кроме того, как бы я изменил код так, чтобы он загружал несинхронный поток байтов (но со случайными паузами между каждым пакетом байтов) асинхронно вместо строки? Как бы я интегрировал чтение этого потока байтов по мере его поступления? Я понимаю, что это больше, чем один вопрос, но, поскольку все они тесно связаны, я решил, что один вопрос сэкономит время.

Заранее спасибо,

Bob

P.S. Поскольку я все еще новичок в F #, пожалуйста, не стесняйтесь вносить любые изменения / предложения в мой код, который показывает, как это делается в более функциональном стиле. Я действительно пытаюсь избавиться от своего мышления в C #, поэтому я ценю любые советы, которыми кто-то может поделиться.

Редактировать: Я случайно вставил неправильный фрагмент, который я использовал. Я внес изменения в фрагмент Томаса и забыл об этом.

Ответы [ 2 ]

3 голосов
/ 04 апреля 2011

Когда я пытаюсь запустить ваш код, downloadPage(url, postData) не работает, поскольку downloadPage ожидает две отдельные строки. downloadPage url postData - это то, что ожидается.

Если вы изменили привязку let к форме кортежа или let downloadPage(url:string, postData:string), ваш вызов также сработал бы.

Объяснить, почему вы получили ошибку, которую вы получили, сложнее. Форма Curried создает функцию, которая возвращает функцию или string -> string -> Async<string> в вашем случае. Поэтому компилятор увидел, что вы передали один параметр (в конце концов, кортежи - это отдельные элементы) и увидел, что результатом должен быть string -> Async<string>, который не совместим с Async<string>. Другая ошибка, которую он мог бы найти (и сделал в моем случае), заключается в том, что string * string несовместим с string. Точная ошибка: Expected string but found 'a * 'b.

0 голосов
/ 04 апреля 2011

Вот что у меня было:

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

это то, что сработало после продолжения случайного угадывания:

Async.RunSynchronously (downloadPage url postData);;

Хотя я не уверен, почему это изменение решило проблему. Мысли?

...