user10632986
user10632986

Reputation:

Create a list of a discriminate union type with 3 different primitive types

So I am attempting to create a list of a discriminate union type such as;

type ColType = Int of int | Float of float | String of string 

And then insert into a list, such as

let addToList (list : ColType list) (col : ColType) =
let list' = list @[col]
list'

However I am unsure how to initialize the coltype values as I only get values such as int -> coltype etc.

I tried this function

let createColType x = 
    if x.GetType() = int then  
        Int x
    else if x.GetType() = float then 
        Float x 
    else if x.GetType() = string then  
        String x
    else 
        String x

Which obviously doesnt work as it will return different values, so how would you go about solving this?

Upvotes: 2

Views: 244

Answers (2)

VoronoiPotato
VoronoiPotato

Reputation: 3183

type Food = Hamburgers of int | Soda of float | Other of string 
module Food = 
    let tryCreate food = 
        match box food with
        | :? int as i -> Some(Hamburgers i)
        | :? float as f -> Some(Soda f)
        | :? string as s -> Some(Other s)
        | _ -> None

let burgers = Hamburgers 7
let soda = Soda 3.2
let mozzarellaSticks = Other "Mozzarella Sticks"
let mysteryMeat = Option.toList(Food.tryCreate "nobody knows")

let list = [burgers; soda; mozzarellaSticks] @ mysteryMeat

By using an Option as the return type for my tryCreate I will not get any runtime exception. You'll notice also that I've tried to create DU labels that associate with my business goals. This makes it easier to express intent, and makes the unions more useful than simple ints, strings, and floats. Most of the time I know what type I have because the type corresponds to a business use, so I don't have to write or use a tryCreate. Often in practice it's not meaningfully possible to map primitives to our discriminated unions, consider for example if we added a | Hotdogs of int it's ambiguous if any int we add is a hotdog or a hamburger.

Upvotes: 0

AMieres
AMieres

Reputation: 5004

Use match to check multiple options and :? to match the type:

let createColType x = 
    match box x with
    | :? int    as i -> ColType.I i
    | :? float  as f -> ColType.F f
    | :? string as s -> ColType.S s
    |_-> failwithf "Type not supported %A" <| x.GetType().FullName

createColType  1  |> printfn "%A" // shows:  I 1
createColType  2. |> printfn "%A" // shows:  F 2.0
createColType "3" |> printfn "%A" // shows:  S "3"

Upvotes: 1

Related Questions