该表达式应该具有IWebProxy类型,但这里有类型WebProxy

时间:2013-08-17 12:35:39

标签: types f#

我正在玩一个来自this nice tutorial的f#的简单示例。并遇到了这个非常奇怪的错误。在向webrequest添加代理之后,它告诉我类型WebProxy与预期类型IWebProxy不兼容。这有点奇怪,为什么我的C#锤子在F#中无法工作?

我在这里做错了什么?

let downloadUrlToFile url file =
    let req = WebRequest.Create(Uri(url))
    req.Proxy = new WebProxy("127.0.0.1", 444)
    use res = req.GetResponse()
    use stream = res.GetResponseStream()
    use reader = new IO.StreamReader(stream)
    let timestamp = DateTime.UtcNow.ToString("yyy-MM-dd")
    let path = sprintf "%s.%s.html" file timestamp
    use writer = new IO.StreamWriter(path)
    writer.Write(reader.ReadToEnd())
    printfn "done loading %s to %s" url file

错误消息

This expression was expected to have type
    IWebProxy    
but here has type
    WebProxy    

3 个答案:

答案 0 :(得分:4)

正如其他人已经解释的那样,问题是=是比较运算符。在这种情况下,您需要一个<-的作业。

但是,F#实际上会在几种情况下隐式执行upcast,并且赋值就是其中之一,因此您无需添加:> IWebProxy来转换对象。以下内容可以正常使用:

req.Proxy <- new WebProxy("127.0.0.1", 444)

除了赋值,F#还在将参数传递给方法或函数时进行隐式向上转换。对于比较运算符,它不会这样做(因为你想知道,没有任何歧义,比较什么类型。)

答案 1 :(得分:1)

嗯,至少有两件事,你不希望在这里:

  • req.Proxy = new WebProxy(...)是一种比较,您可能需要req.Proxy <- new WebProxy(...)代替。
  • F#不进行自动向上转换。因此,您可能需要使用req.Proxy <- new WebProxy(...) :> _之类的内容进行静态上传。这告诉F#&#34; upcast到这里适合的任何东西&#34;。

(我实际上并没有运行你的代码,所以你可能会有更多的问题,但这两个对于C#程序员来说当然很重要。)

答案 2 :(得分:1)

F#不会像C#那样自动转发值,因此您需要将WebProxy对象显式地转换为IWebProxy,如下所示:

req.Proxy <- WebProxy("127.0.0.1", 444) :> IWebProxy

同样重要的是:F#中的赋值语法为<-,而不是C#中的=。如果您使用=,则会收到如下错误消息:

Type constraint mismatch. The type 
    bool    
is not compatible with type
    IWebProxy    
The type 'bool' is not compatible with the type 'IWebProxy'