F#如何通过匹配语句确定值的类型?

时间:2014-11-14 19:34:15

标签: f#

这是我的问题:

let foo =
    match bar with
            | barConfig1 ->                configType1(devices:DeviceEntities,DeviceStartIndex,inputStartIndex,outputStartIndex)
            | barConfig2 -> configType2(devices:DeviceEntities,DeviceStartIndex,inputStartIndex,outputStartIndex)
            | barConfig3 -> configType3(devices:DeviceEntities,DeviceStartIndex,inputStartIndex,outputStartIndex)
            | barConfig4 -> configType4(devices:DeviceEntities,DeviceStartIndex,inputStartIndex,outputStartIndex)

我希望foo的类型由match语句决定,但它总是将foo设置为第一种类型。

type bar =
|barConfig1
|barConfig2
|barConfig3
|barConfig4

2 个答案:

答案 0 :(得分:4)

在F#中,没有语句,只有表达式,每个表达式都必须具有单一的具体类型。 match块也是一个表达式,这意味着它必须具有单个具体类型。接下来是匹配的每个案例都必须具有相同的类型。

也就是说,这样的东西不是有效的F#:

let foo =               // int? string?
    match bar with      // int? string?
    | Int    -> 3       // int
    | String -> "Three" // string

在这种情况下,类型推断机制将期望匹配的类型与第一个case的类型相同 - int,并且当它在第二个中看到字符串时最终会混淆。在您的示例中,同样的事情发生 - 类型推断要求所有情况都返回configType1。

解决这个问题的方法是将值转换为常用的超类型或接口类型。因此,对于您的情况,假设configTypes实现了一个通用的IConfigType接口:

 let foo =   // IConfigType
    let arg = (devices:DeviceEntities,DeviceStartIndex,inputStartIndex,outputStartIndex)
    match bar with
    | barConfig1 -> configType1(arg) :> IConfigType
    | barConfig2 -> configType2(arg) :> IConfigType
    | barConfig3 -> configType3(arg) :> IConfigType
    | barConfig4 -> configType4(arg) :> IConfigType

答案 1 :(得分:0)

如果输出类型的个案数量有限,您也可以将其作为一个有区别的联合:

type ConfigType =
    | ConfigType1 of configType1
    | ConfigType2 of configType2
    | ConfigType3 of configType3
    | ConfigType4 of configType4``

let foo =
    match bar with
        | barConfig1 -> ConfigType1 <| configType1(devices:DeviceEntities,DeviceStartIndex,inputStartIndex,outputStartIndex)
        | barConfig2 -> ConfigType2 <| configType2(devices:DeviceEntities,DeviceStartIndex,inputStartIndex,outputStartIndex)
        | barConfig3 -> ConfigType3 <| configType3(devices:DeviceEntities,DeviceStartIndex,inputStartIndex,outputStartIndex)
        | barConfig4 -> ConfigType4 <| configType4(devices:DeviceEntities,DeviceStartIndex,inputStartIndex,outputStartIndex)``

或者,如果它们都实现了一个接口或继承了一些基类,那么你可以向上转发,就像scrwtp的回答一样。