F# - 我可以从函数返回一个有区别的联合

bst*_*ack 11 f# functional-programming discriminated-union

我有以下类型:

type GoodResource = {
    Id:int;
    Field1:string }


type ErrorResource = {
    StatusCode:int;
    Description:string }
Run Code Online (Sandbox Code Playgroud)

我有以下歧视联盟:

type ProcessingResult = 
    | Good of GoodResource
    | Error of ErrorResource
Run Code Online (Sandbox Code Playgroud)

然后想要一个具有被区分联合ProcessingResult的返回类型的函数:

let SampleProcessingFunction value =
    match value with
    | "GoodScenario" -> { Id = 123; Field1 = "field1data" }
    | _ -> { StatusCode = 456; Description = "desc" }
Run Code Online (Sandbox Code Playgroud)

是我想做的事情.编译器发出声明它希望GoodResource是返回类型.我错过了什么,或者我是否完全以错误的方式解决这个问题?

Gru*_*oon 17

就目前而言,每个分支SampleProcessingFunction返回两种不同的类型.

要返回相同的类型,您需要创建一个DU(您已经这样做),但也要明确指定DU的大小写,如下所示:

let SampleProcessingFunction value =
    match value with
    | "GoodScenario" -> Good { Id = 123; Field1 = "field1data" }
    | _ -> Error { StatusCode = 456; Description = "desc" }
Run Code Online (Sandbox Code Playgroud)

您可能会问"为什么编译器无法自动找出正确的情况",但如果您的DU有两个相同类型的情况会怎样?例如:

type GoodOrError = 
    | Good of string
    | Error of string
Run Code Online (Sandbox Code Playgroud)

在下面的示例中,编译器无法确定您的意思是:

let ReturnGoodOrError value =
    match value with
    | "GoodScenario" -> "Goodness"
    | _ -> "Badness"
Run Code Online (Sandbox Code Playgroud)

所以你需要使用构造函数来处理你想要的情况:

let ReturnGoodOrError value =
    match value with
    | "GoodScenario" -> Good "Goodness"
    | _ -> Error "Badness"
Run Code Online (Sandbox Code Playgroud)


小智 10

您必须说明要在任一分支中返回的联合类型的情况.

let SampleProcessingFunction value =
    match value with
    | "GoodScenario" -> { Id = 123; Field1 = "field1data" } |> Good
    | _ -> { StatusCode = 456; Description = "desc" } |> Error
Run Code Online (Sandbox Code Playgroud)

我建议阅读Scott Wlaschin 铁路编程的这篇优秀文章


sep*_*p2k 7

{ Id = 123; Field1 = "field1data" }是类型的值GoodResource,而不是类型的值ProcessingResult.要创建类型的值ProcessingResult,您需要使用其两个构造函数之一:GoodError.

所以你的函数可以像这样写:

let SampleProcessingFunction value =
    match value with
    | "GoodScenario" -> Good { Id = 123; Field1 = "field1data" }
    | _ -> Error { StatusCode = 456; Description = "desc" }
Run Code Online (Sandbox Code Playgroud)