Is it possible to pass discriminated union tags as arguments?

前端 未结 5 1412
不思量自难忘°
不思量自难忘° 2020-12-31 17:04

Is it possible to pass the type of a discriminated union tag to another function so it can use it for pattern matching?

Non working example of what I mean:



        
5条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-12-31 17:46

    No, it's not possible to pass just the tag, in order to be able to treat separately the tag and the string you can define them like this:

    type AnimalType = Pig  | Cow  | Fish
    type Animal = Animal of AnimalType * string
    
    let animals = [Animal (Pig, "Mike"); Animal (Pig, "Sarah"); Animal (Fish, "Eve"); Animal (Cow, "Laura"); Animal (Pig, "John")]
    
    let rec filterAnimals animalType animals =
        if animals = [] then
            []
        else
            let rest = filterAnimals animalType (List.tail animals)
            match List.head animals with
            | Animal (x, animal) when x = animalType -> animal::restwork
            |_ -> rest
    
    printfn "%A" (filterAnimals Pig animals)
    

    Alternatively you can use just a tuple of AnimalType * string

    UPDATE

    Regarding your question in the comments about what happens if the structure is not always the same, there's a trick you can use: you can compare the type of two Discriminated Unions since each tag is compiled to a different sub-class.

    type Animal = 
        | Person of string * string 
        | Pig of string 
        | Cow of string 
        | Fish of string
    
    let animals = [Pig "Mike"; Pig "Sarah"; Fish "Eve"; Cow "Laura"; Pig "John"]
    
    let rec filterAnimals animalType animals =
        if animals = [] then
            []
        else
            let rest = filterAnimals animalType (List.tail animals)
            match List.head animals with
            | x when animalType.GetType() = x.GetType() -> x::rest
            |_ -> rest
    
    printfn "%A" (filterAnimals (Pig "") animals)
    

    But before going this way, you should think if you really need to model your problem like this.

    Even if you decide to go with this structure I would rather use the built-in filter function, see the solution proposed by @polkduran.

提交回复
热议问题