2012-02-03 60 views
0

我有2套可識別聯合:F#:嵌套歧視工會和匹配

type ServiceTypes = 
    | Contexts 
    | Context of int 
    | Producers 

type ServiceActions = 
    | Get of ServiceTypes 
    | Update of ServiceTypes 

和嵌套的match語句:

let s_action = match action with 
       | Get(stype) -> sprintf "Get%s" (match stype with 
               | Contexts -> sprintf "Contexts" 
               | Context(id) -> (sprintf "Context/%d" id)) 
               | _ -> raise (RequestException("get")) 
       | Update(stype) -> sprintf "Update%s" (match stype with 
                 | Producers -> (sprintf "Producers") 
                 | _ -> raise (RequestException("update"))) 

的目標是建立與呼叫看起來像一個請求字符串那req.Send(Update Producers)

反正我不明白一個道理,編譯器給了我2個警告:

    Update(stype)
  1. 我得到此規則將永遠不會在第一match stype我匹配
  2. 得到一個這個表達式的不完整模式匹配。例如,值'生產者'可能表示模式未涵蓋的情況。

所以問題是爲什麼我會得到這兩個警告?我在配對作品的路上錯過了什麼?

回答

5

您的左括號在錯誤的地方。

| Context(id) -> (sprintf "Context/%d" id)) 
| _ -> raise (RequestException("get")) 

應該

| Context(id) -> (sprintf "Context/%d" id) 
| _ -> raise (RequestException("get"))) 

事實上,爲了清楚起見,我將擺脫所有多餘的括號(在這種情況下,實際上是每一個括號):

let s_action = 
    match action with 
    | Get stype -> match stype with 
         | Contexts -> "Contexts" 
         | Context id -> sprintf "Context/%d" id 
         | _   -> RequestException "get" |> raise 
         |> sprintf "Get%s" 
    | Update stype -> match stype with 
         | Producers -> "Producers" 
         | _   -> RequestException "update" |> raise 
         |> sprintf "Update%s" 

我個人覺得這更具可讀性,但當然這是次現在是YMMV。

+0

Arf ...我以爲我不明白模式匹配:P至少這只是一個愚蠢的語法錯誤。關於如何擺脫我非常喜歡的額外括號的大演示(我更新了我的代碼)。非常感謝您的寶貴時間! – 2012-02-03 23:06:49

1

既然你在錯誤的點關閉了paratheses,你的代碼實際上就變成了:

let s_action = 
    match action with 
    | Get(stype) -> sprintf "Get%s" (match stype with 
            | Contexts -> sprintf "Contexts" 
            | Context(id) -> (sprintf "Context/%d" id)) 
    | _ -> raise (RequestException("get")) (* Closing parenthesis should be here *) 
    | Update(stype) -> sprintf "Update%s" (match stype with 
             | Producers -> (sprintf "Producers") 
             | _ -> raise (RequestException("update"))) 

很明顯,你可以看到第一個match stype with不包括Producers和最後的模式Update(stype)從未因以前的模式匹配_。因此,所有編譯器警告都是合理的。

你似乎過度使用假體;這裏是一個清理版本:

let s_action = 
match action with 
| Get stype -> sprintf "Get%s" <| match stype with 
            | Contexts -> sprintf "Contexts" 
            | Context id -> sprintf "Context/%d" id 
            | _ -> raise <| RequestException "get" 
| Update stype -> sprintf "Update%s" <| match stype with 
             | Producers -> sprintf "Producers" 
             | _ -> raise <| RequestException "update" 
9

雖然嵌套匹配表達式有時必要的,在這個特殊的情況下,我會寫一個更可讀的單級的比賽,我要是你:

let s_action = 
    match action with 
    | Get Contexts  -> "GetContexts" 
    | Get (Context id) -> sprintf "GetContext/%d" id 
    | Update Producers -> "UpdateProducers" 
    | Get _ -> raise (RequestException "get") 
    | Update _ -> raise (RequestException "update") 

這達到與您的代碼完全相同的效果。

+0

+1,我也很喜歡這個解決方案。 – ildjarn 2012-02-04 21:56:31