In F#, How can I attach metadata to discriminated union values?

自闭症网瘾萝莉.ら 提交于 2019-12-13 18:44:38

问题


I want to create something that's kind of like an enum with an F# record type for a value instead of an int. For example, if I've got the union:

type BologneseIngredients = | Spaghetti
                            | Tomatoes
                            | MincedBeef
                            | GrandmasSecretIngredient

I know that spaghetti is always 30cm long and tomatoes are always red. What I could do is have a 'get metadata' function:

let getMetadata = function
                    | Spaghetti -> { length: 30.0<cm> }
                    | Tomatoes -> { colour: Color.Red }
                    | _ -> { }

but I'd really like to keep the definition of the union and the data together. Is there a nice way to do this?


回答1:


my suggestion:

module Recipes =

    type BologneseIngredients = | Spaghetti
                                | Tomatoes
                                | MincedBeef
                                | GrandmasSecretIngredient

    let length (ind : BologneseIngredients) : float<cm> option =
         match ind with
         | Sphaghetti -> Some 30.0<cm>
         | _ -> None

    // .. or a bit more "metadata"ish
    type Metadata = 
        | Length of float<cm>
        | Color of System.Drawing.Color

    let metadata = 
       function
       | Sphaghetti -> [ Length 30.0<cm ]
       | Tomatoes   -> [ Color System.Drawing.Color.Red ]
       | ...

    let metaLength meta =
       meta |> List.tryPick (function | Length l -> Some l | _ -> None)

    let getLength = metadata >> metaLength



回答2:


You could add properties to your discriminated union...

type BologneseIngredients = 
    | Spaghetti
    | Tomatoes
    | MincedBeef
    | GrandmasSecretIngredient

    member x.Color =
        match x with
        | Spaghetti -> Color.AntiqueWhite
        | Tomatoes -> Color.Red
        | MincedBeef -> Color.Firebrick
        | GrandmasSecretIngredient -> Color.Transparent



let foo = Tomatoes

printfn "%A" foo.Color

> Color [Red]


来源:https://stackoverflow.com/questions/25059587/in-f-how-can-i-attach-metadata-to-discriminated-union-values

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