我有2个嵌套的歧视联盟:
type ServiceTypes =
| Contexts
| Context of int
| Producers
type ServiceActions =
| Get of ServiceTypes
| Update of ServiceTypes
一个嵌套的匹配语句:
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)
我得到此规则永远不会匹配 match stype
上我得到一个不完整模式匹配此表达式。例如,值“生产者”可能表示模式未涵盖的案例。 所以问题是为什么我会收到这两个警告?我是否错过了匹配工作的方式?
答案 0 :(得分:11)
虽然嵌套匹配表达式有时是有保证的,但在这种特殊情况下,如果我是你,我会写一个更易读的单级匹配:
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")
实现与您的代码完全相同的效果。
答案 1 :(得分:6)
您的右括号位于错误的位置。
| 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。
答案 2 :(得分:2)
由于您在错误的位置关闭了副作用,因此您的代码实际上变为:
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"