2015-04-22 23 views
10

Ho le seguenti tipologie:F # - Posso restituire un'unione discriminata da una funzione

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


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

Ho il seguente unione discriminati:

type ProcessingResult = 
    | Good of GoodResource 
    | Error of ErrorResource 

Poi vuole avere una funzione che avrà un tipo di ritorno dell'unione discriminata ProcessingResult:

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

È quello che sto cercando di fare possibile. Il compilatore sta emettendo affermando che si aspetta che GoodResource sia il tipo restituito. Cosa mi sto perdendo o sto andando completamente in questo modo sbagliato?

risposta

16

Così com'è, SampleProcessingFunction restituisce due diverse tipi per ogni ramo.

per restituire lo stesso tipo , è necessario creare un DU (che avete fatto), ma anche specificare il caso del DU esplicitamente, in questo modo:

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

Si potrebbe chiedere "perché puo' t il compilatore capisce automaticamente il caso corretto ", ma cosa succede se il tuo DU ha due casi dello stesso tipo nello stesso ? Per esempio:

type GoodOrError = 
    | Good of string 
    | Error of string 

Nell'esempio riportato di seguito, il compilatore non è in grado di determinare qual caso cercavi:

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

Così ancora una volta è necessario utilizzare la funzione di costruzione per il caso che si desidera:

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

È necessario indicare il caso del tipo di unione che si desidera restituire in entrambi i rami.

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

suggerisco di leggere questo eccellenti articoli di Scott Wlaschin Railway Oriented Programming

7

{ Id = 123; Field1 = "field1data" } è un valore di tipo GoodResource, non di tipo ProcessingResult. Per creare un valore di tipo ProcessingResult, è necessario utilizzare uno dei suoi due costruttori: Good o Error.

Quindi la funzione può essere scritta in questo modo:

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