2014-11-14 77 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的答案一樣。