F# - Can I return a discriminated union from a function

半城伤御伤魂 提交于 2019-12-10 01:50:06

问题


I have the following types:

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


type ErrorResource = {
    StatusCode:int;
    Description:string }

I have the following discriminated union:

type ProcessingResult = 
    | Good of GoodResource
    | Error of ErrorResource

Then want to have a function that will have a return type of the discriminated union ProcessingResult:

let SampleProcessingFunction value =
    match value with
    | "GoodScenario" -> { Id = 123; Field1 = "field1data" }
    | _ -> { StatusCode = 456; Description = "desc" }

Is what I am trying to do possible. The compiler is giving out stating that it expects GoodResource to be the return type. What am I missing or am I completely going about this the wrong way?


回答1:


As it stands, SampleProcessingFunction returns two different types for each branch.

To return the same type, you need to create a DU (which you did) but also specify the case of the DU explicitly, like this:

let SampleProcessingFunction value =
    match value with
    | "GoodScenario" -> Good { Id = 123; Field1 = "field1data" }
    | _ -> Error { StatusCode = 456; Description = "desc" }

You might ask "why can't the compiler figure out the correct case automatically", but what happens if your DU has two cases of the same type? For example:

type GoodOrError = 
    | Good of string
    | Error of string

In the example below, the compiler cannot determine which case you mean:

let ReturnGoodOrError value =
    match value with
    | "GoodScenario" -> "Goodness"
    | _ -> "Badness"

So again you need to use the constructor for the case you want:

let ReturnGoodOrError value =
    match value with
    | "GoodScenario" -> Good "Goodness"
    | _ -> Error "Badness"



回答2:


You have to state the case of the union type you want to return in either branch.

let SampleProcessingFunction value =
    match value with
    | "GoodScenario" -> { Id = 123; Field1 = "field1data" } |> Good
    | _ -> { StatusCode = 456; Description = "desc" } |> Error

I suggest to read this excellent articles by Scott Wlaschin Railway Oriented Programming




回答3:


{ Id = 123; Field1 = "field1data" } is a value of type GoodResource, not of type ProcessingResult. To create a value of type ProcessingResult, you need to use one of its two constructors: Good or Error.

So your function can be written like this:

let SampleProcessingFunction value =
    match value with
    | "GoodScenario" -> Good { Id = 123; Field1 = "field1data" }
    | _ -> Error { StatusCode = 456; Description = "desc" }


来源:https://stackoverflow.com/questions/29801418/f-can-i-return-a-discriminated-union-from-a-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!