在F#中声明C#类联合的麻烦

时间:2014-06-16 14:37:14

标签: f#

我正在使用Forecast.io C#天气库,它提供了几个不同时间段(例如,每小时,每天,“现在”)的天气预报类,它们都包含类似的数据。

我正在尝试编写接受任何这些类的函数,但是我得到一些我不理解的编译错误(下面):

  1. 对于FS0001错误,为什么getTemp函数对与Forecast联合类型匹配的对象不满意?为什么在每种情况下都期望不同的参数类型?

  2. 对于FS0019错误,它指的是什么构造函数?为什么期望我为这个构造函数提供参数?

  3. 以下是一些示例代码:

    open ForecastIO
    
    type Forecast = 
        | Currently of ForecastIO.Currently
        | HourForecast of ForecastIO.HourForecast
    
    let getTemp forecast =
        match forecast with
            | Currently -> forecast.temperature
            | HourForecast -> forecast.temperature
        |> float
    
    let forecastForDate date = 
        let request = new ForecastIORequest("api_key", 35.780556f, -78.638889f, date, Unit.us);
        request.Get ()
    
    let test () = 
        let baseDate = System.DateTime.Parse "2014-06-12 22:00:00"
        let forecast = forecastForDate baseDate
    
        forecast
        |> (fun r -> r.currently)
        |> getTemp
        |> printfn "%f"
    
        forecast
        |> (fun r -> r.hourly.data.[0])
        |> getTemp
        |> printfn "%f"
    
    test ()
    

    这是我的编译器输出:

    /tmp/forecast.io/test2.fs(9,15): error FS0019: This constructor is applied to 0 argument(s) but expects 1
    
    /tmp/forecast.io/test2.fs(23,12): error FS0001: Type mismatch. Expecting a
        Currently -> 'a    
    but given a
        Forecast -> float    
    The type 'Currently' does not match the type 'Forecast'
    
    /tmp/forecast.io/test2.fs(28,12): error FS0001: Type mismatch. Expecting a
        HourForecast -> 'a    
    but given a
        Forecast -> float    
    The type 'HourForecast' does not match the type 'Forecast'
    

3 个答案:

答案 0 :(得分:5)

有一些不同的问题。一个是@mydogisbox提到的 - 如果您的DU案例有字段,您需要在模式匹配中考虑它们,或者用_忽略它们或者捕获一些标识符。

但主要问题是,您不是在任何地方创建DU的实例。预测对象的.currently属性可能属于ForecastIO.Currently类型,.hourly.data.[0]类型为ForecastIO.HourForecast,但这并不意味着您可以采用这些值并对待他们喜欢你Forecast DU的情况。您需要明确构造所需的案例:

  forecast
  |> (fun r -> Currently(r.currently))
  |> getTemp
  |> printfn "%f"

  forecast
  |> (fun r -> HourForecast(r.hourly.data.[0]))
  |> getTemp
  |> printfn "%f"

如果你不想定义DU,而只是想要根据输入的类型进行模式匹配,你可以做类似@Jan建议的事情,甚至不必定义DU:< / p>

let getTemp forecast =
    match forecast with
        | :? ForecastIO.Currently as c -> c.temperature
        | :? ForecastIO.HourForecast as h -> h.temperature
    |> float

答案 1 :(得分:4)

分解DU时,您需要指定构造函数参数的名称(即构造DU情况所需的参数)。在这种情况下,你不想使用它们,所以你可以像这样将它们删空:

let getTemp forecast =
    match forecast with
        | Currently _ -> forecast.temperature
        | HourForecast _ -> forecast.temperature
    |> float

答案 2 :(得分:0)

更好地完成以下工作?

let getTemp forecast =
    match forecast with
        | :? Currently as c -> c.temperature
        | :? HourForecast as h -> h.temperature
    |> float