F#:嵌套的区分联合和匹配

Nic*_*ume 1 f# pattern-matching discriminated-union

我有2个嵌套的歧视联盟:

type ServiceTypes =
    | Contexts
    | Context of int
    | Producers

type ServiceActions =
    | Get of ServiceTypes
    | Update of ServiceTypes
Run Code Online (Sandbox Code Playgroud)

和嵌套的匹配语句:

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")))
Run Code Online (Sandbox Code Playgroud)

目标是使用看起来像这样的调用来构建请求字符串req.Send(Update Producers).

无论如何,由于我不理解的原因,编译器给了我2个警告:

  1. Update(stype)我得到一个这个规则永远不会匹配
  2. 在第一个match stype我得到一个不完整的模式匹配这个表达式.例如,值'Producers'可以指示模式未涵盖的情况.

所以问题是为什么我会收到这两个警告?我是否错过了匹配工作的方式?

kkm*_*kkm 13

虽然嵌套匹配表达式有时是有保证的,但在这种特殊情况下,如果我是你,我会写一个更易读的单级匹配:

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")
Run Code Online (Sandbox Code Playgroud)

它实现了与您的代码完全相同的效果.


ild*_*arn 6

您的右括号位于错误的位置.

| Context(id)  -> (sprintf "Context/%d" id))
| _ -> raise (RequestException("get"))
Run Code Online (Sandbox Code Playgroud)

应该

| Context(id)  -> (sprintf "Context/%d" id)
| _ -> raise (RequestException("get")))
Run Code Online (Sandbox Code Playgroud)

实际上,为了清楚起见,我将摆脱所有无关的括号(在这种情况下实际上是每个括号):

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"
Run Code Online (Sandbox Code Playgroud)

就个人而言,我发现这更具可读性,但当然这是主观的,所以YMMV.