In F #, is it possible to check if two values ​​have the same constructor?

Assuming I have a large type of delimited union:

type Thing =
    | One of int
    | Two of string
    | Three of bool option
      ...

And I have this function:

let comp a b = match a, b with
    | One _, One _ -> true
    | Two _, Two _ -> true
      ...
    | _, _ -> false

Is there a way to write a function more neat, in short, which does not require me to list each constructor?

+4
source share
2 answers

In principle, this is not possible. Even if you can get constructors for your values, they are not comparable, because they are functions. The template bit is involved there, but you can define tag values ​​and a function to bind to tags:

let thingCase thing =
    match thing with
    | One _ -> 1
    | Two _ -> 2
    | Three _ -> 3

let comp a b = thingCase a = thingCase b

It is flexible enough to work with sequences:

let compSeq things =
    things
    |> Seq.map thingCase
    |> Seq.pairwise
    |> Seq.forall (fun (a, b) -> a = b)

: , .

+3

, , FSharp.Reflection.

open FSharp.Reflection

type Thing =
    | One of int
    | Two of string
    | Three of bool option

let tagOfThing = FSharpValue.PreComputeUnionTagReader(typeof<Thing>)
// val tagOfThing : obj -> int

let isSameThingCase (a: Thing) (b: Thing) =
    tagOfThing a = tagOfThing b

:

> isSameThingCase (One 1) (One 2);;
val it : bool = true
> isSameThingCase (Two "test") (Three None);;
val it : bool = false
+2

Source: https://habr.com/ru/post/1684947/


All Articles