【问题标题】:Discriminated unions in modules模块中的可区分联合
【发布时间】:2015-06-30 19:17:51
【问题描述】:

以下工作如我所料。

type Result =
    | Success
    | Failure

type Response  =
    | Result of Result

let response = Response.Result <| Result.Success

match response with
    | Result result ->
        match result with
        | Result.Success -> printfn "Success"
        | Result.Failure -> printfn "Failure"

但是,当我将其中一些放在模块中时:

module Module =
    type Result =
        | Success
        | Failure

    type Response  =
        | Result of Result        

let response = Module.Response.Result <| Module.Result.Success // <- ERROR HERE

我得到错误:

字段、构造函数或成员'Success'未定义

这也意味着我不能像这样进行匹配:

match response with
    | Module.Result result ->
        match result with
        | Module.Result.Success -> printfn "Success"
        | Module.Result.Failure -> printfn "Failure"

失败了

这不是构造函数或文字,或者构造函数使用不正确

(要让它失败,需要添加一些额外的代码,使Module 有一个createResponse

let createResponse b = 
    if b
    then Response.Result <| Result.Success
    else Response.Result <| Result.Failure

而模块外代码中的response则为let response = Module.createResponse true

难道我不应该在模块中放置一些代码都能够获得相同的结果吗?

【问题讨论】:

  • 看起来像一个错误,因为Success 甚至出现在 Intellisense 中。
  • 是的,也许这真的是一个错误

标签: f#


【解决方案1】:

实际上完全限定名称Module.Result.Success 应该在第一个错误发生的地方起作用。编译器混淆是因为你给两个不同的东西取了相同的名字。 此行将编译:

let response = Module.Response.Result <| Module.Success

您可以通过这种方式进行模式匹配:

match response with
    | Module.Result result ->
        match result with
        | Module.Success -> printfn "Success"
        | Module.Failure -> printfn "Failure"

在最后一个示例中:您将response 值与Module.Result 与参数result 匹配。它只能是Module.Response 类型,因为这种类型的单个案例——即Module.Result——有一个参数。因为这个参数的类型是Module.Result,所以它可以匹配这种类型的两种情况:Module.SuccessModule.Failure。它看起来和听起来令人困惑,因为它是。相同的名称"Result" 被赋予可区分联合类型和另一个可区分联合类型的 case-id。我会将Response 类型更改为这样的:

type Response  =
    | RespResult of Result

【讨论】:

  • 假设Module中还有另外一个类型也有Success和Failure。除非明确指示,否则编译器将如何区分两者?非模块情况下的Result.Success怎么会变成模块情况下的Module.Success
  • 已编辑答案以澄清名称冲突
  • @lejon。是的,看起来像一个错误。完全限定名称应该可以工作。但答案至少提供了一种解决方法。
  • 好的,我会报告的。为了使解决方法更通用,我认为Result 需要为Result&lt;T&gt; 以避免与Success 的其他DU 类型发生冲突。
猜你喜欢
  • 2011-03-10
  • 1970-01-01
  • 2018-11-24
  • 2018-02-03
  • 1970-01-01
  • 2011-11-19
  • 2020-01-24
相关资源
最近更新 更多