Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Return Specific Discriminated Union from Function

Tags:

f#

I have a hierarchy of discriminated unions.

type SpecificNoun =
    | Noun
    | NounPhrase
    | Pronoun
    | PosesivePronoun

type SpecificModifier =
    | Adverb //slowly, quickly, verb + ly (90% of the time)
    | Preposition //off, on, together, behind, before, between, above, with, below

type SpecificVerb =
    | ActionVerb
    | BeingVerb
    | PossesiveVerb
    | TransitiveVerb

type PartsOfSpeech =
    | Noun of SpecificNoun
    | Verb of SpecificVerb
    | Adjective
    | Punctuation
    | Modifier of SpecificModifier

I need to translate a string into one of them, but it has to be a PartOfSpeech so I can use it in my match cases. The below code does not compile.

let StringToPartOfSpeech (part:string) =
    match part with
    | "Noun" -> SpecificNoun.Noun
    | "NounPhrase" -> SpecificNoun.NounPhrase
    | "Pronoun" -> SpecificNoun.Pronoun
    | "PossessivePronoun" -> SpecificNoun.PosesivePronoun
    | "Adverb" ->  SpecificModifier.Adverb

This is a related question to this: F# - Can I return a discriminated union from a function however, in my case, everything is just straight discriminated unions

like image 299
David Crook Avatar asked Jan 20 '26 16:01

David Crook


2 Answers

You need to return a consistent type from all branches. In your case the PartsOfSpeech type is ideal. So that means you need to take a type like SpecificNoun.Noun and wrap it in the appropriate case from PartsOfSpeech.

Also, what if the input string doesn't match any of the cases?

In the code below I decided to return a PartsOfSpeech option, but you could raise an exception, or return a more detailed Success/Failure type, etc.

let StringToPartOfSpeech (part:string) =
    match part with
    | "Noun" -> 
        SpecificNoun.Noun |> PartsOfSpeech.Noun |> Some
    | "NounPhrase" -> 
        SpecificNoun.NounPhrase |> PartsOfSpeech.Noun |> Some
    | "Pronoun" -> 
        SpecificNoun.Pronoun |> PartsOfSpeech.Noun |> Some
    | "PossessivePronoun" -> 
        SpecificNoun.PosesivePronoun |> PartsOfSpeech.Noun |> Some
    | "Adverb" ->  
        SpecificModifier.Adverb |> PartsOfSpeech.Modifier |> Some
    | _ ->  None
like image 129
Grundoon Avatar answered Jan 23 '26 05:01

Grundoon


Your code doesn't compile because you are returning two values with different types :

let StringToPartOfSpeech (part:string) =
    match part with
    | "Noun" -> Noun // type of SpecificNoun
    | "NounPhrase" ->NounPhrase  // type of SpecificNoun
    | "Pronoun" -> Pronoun  // type of SpecificNoun
    | "PossessivePronoun" ->PosesivePronoun  // type of SpecificNoun
    | "Adverb" ->  Adverb // type of SpecificModifier

Why you didn't use your type PartsOfSpeech ?

Try the following code :

 type PartsOfSpeech =
        | PNoun of SpecificNoun
        | PVerb of SpecificVerb
        | PAdjective
        | PPunctuation
        | PModifier of SpecificModifier
        | PUnknown

let StringToPartOfSpeech (part:string) =
    match part with
    | "Noun" -> PNoun (Noun)
    | "Adverb" ->  PModifier (Adverb)
    | _ -> PUnknown

Plus, to avoid compiler warnings, I add a case for a Unknown String.

like image 36
alifirat Avatar answered Jan 23 '26 05:01

alifirat



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!