2014-11-14 47 views
0

这里是我的问题: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的类型由匹配语句来决定,但它始终将foo的第一个类型。

type bar = 
|barConfig1 
|barConfig2 
|barConfig3 
|barConfig4 
+0

请添加'bar'类型的定义。 – Lee 2014-11-14 19:50:43

+0

这不可能是正确的 - 您的'bar'定义会引发错误,因为这些个案必须以大写字母开头。 – Tarmil 2014-11-15 10:41:21

回答

4

在F#中,没有任何语句,只有表达式和每个表达式必须有一个具体的类型。 A match块也是一个表达式,这意味着它必须具有单个具体类型。接下来的是,每场比赛的情况都必须具有相同的类型。

也就是说,这样的事情是不是有效的F#:

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

在这种情况下,类型推理机制将期待比赛的类型是一样的第一种情况的类型 - 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 
+0

非常感谢。这有助于。 – 2014-11-17 14:21:39

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的答案一样。