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

spi*_*ech 1 f#

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

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

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

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

这是一些示例代码:

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 ()
Run Code Online (Sandbox Code Playgroud)

这是我的编译器输出:

/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'
Run Code Online (Sandbox Code Playgroud)

lat*_*kin 5

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

但是,主要问题是你不是在任何地方创建你的DU实例..currently预测对象的属性可能是类型ForecastIO.Currently.hourly.data.[0]类型ForecastIO.HourForecast,但这并不意味着您可以将这些值视为来​​自ForecastDU的案例.您需要显式构造所需的案例:

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

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

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

let getTemp forecast =
    match forecast with
        | :? ForecastIO.Currently as c -> c.temperature
        | :? ForecastIO.HourForecast as h -> h.temperature
    |> float
Run Code Online (Sandbox Code Playgroud)