Создайте список различающегося типа объединения с 3 различными типами примитивов.

Итак, я пытаюсь создать список различных типов союзов, таких как;

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

А затем вставьте в список, например

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

Однако я не уверен, как инициализировать значения coltype, поскольку я получаю только такие значения, как int -> coltype и т. д.

я попробовал эту функцию

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

Что, очевидно, не работает, так как будет возвращать разные значения, так как бы вы решили это?


person Community    schedule 20.03.2019    source источник
comment
Как вы используете функцию createColType? Вы используете его для типизированных значений или для значений типа obj?   -  person hvester    schedule 20.03.2019
comment
Что представляют ваши int, float и string? Почему вы не хотите разрешить десятичную дробь? Если они представляют собой бизнес-ограничения, вы можете рассмотреть возможность предоставления этих реальных имен, которые соответствуют потребностям вашего бизнеса.   -  person VoronoiPotato    schedule 20.03.2019


Ответы (2)


Используйте match для проверки нескольких вариантов и :? для соответствия типу:

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"
person AMieres    schedule 20.03.2019
comment
Используемое здесь сопоставление типового тестового шаблона является правильным подходом. Но я обычно предпочитаю возвращать тип результата, используя Ok и Error, а не генерировать исключение. Затем любой код, вызывающий эту функцию, может решить, стоит ли создавать исключение для неподдерживаемого типа и, возможно, взорвать приложение. - person TheQuickBrownFox; 20.03.2019
comment
Я очень скептически отношусь к их фактическим типам String, Int, Float. Кроме того, DU предотвращает необходимость любого отказоустойчивости. - person VoronoiPotato; 20.03.2019

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

Используя Option в качестве типа возвращаемого значения для моего tryCreate, я не получу никаких исключений во время выполнения. Вы также заметите, что я пытался создать ярлыки DU, которые связаны с моими бизнес-целями. Это упрощает выражение намерений и делает объединения более полезными, чем простые целые числа, строки и числа с плавающей запятой. Большую часть времени я знаю, какой тип у меня есть, потому что тип соответствует бизнес-использованию, поэтому мне не нужно писать или использовать tryCreate. Часто на практике невозможно осмысленно сопоставить примитивы с нашими размеченными объединениями, например, если мы добавили | Hotdogs of int, это неоднозначно, если любое добавляемое целое является хот-догом или гамбургером.

person VoronoiPotato    schedule 20.03.2019