在有区别的联合中共享一个元组类型

sharing a tuple type in a discriminated union

假设我们有

type MyTuples =
    | One of a: string * b: string * c: string
    | Two of a: string * b: string * c: string * d: string
    | Three of a: string * b: string * c: string * e: string * f: int

DU的病例之间不能共享a: string * b: string * c: string吗?

大概是这样的:

type MyOne = One of a: string * b: string * c: string // the single-case DU

type MySharingTuples =
    | One of MyOne
    | Two of MyOne * d: string
    | Three of MyOne * e: string * f: int

let myTwo = MyTuples.Two (a = "1", b = "2", c = "3", d = "4")

let mySharingTwo = MySharingTuples.Two (MyOne.One (a = "1", b = "2", c = "3"), d = "4")

myTwo |> printfn "%A"
mySharingTwo |> printfn "%A"

打印

Two ("1", "2", "3", "4")
Two (One ("1", "2", "3"), "4")

从类型论的角度来看,myTwomySharingTwo 不相等,编译器甚至不允许我们在运行时证明这一点。但是从集合论的角度来看,Two ("1", "2", "3", "4")Two (One ("1", "2", "3"), "4") 看起来像:

("1", "2", "3", "4") = (("1", "2", "3"), "4")

我的旧数学书告诉我那里有等价物。

MyTuples是否违反了DRY原则?有什么方法可以证明 MyOne 等同于 MyTuples.One?这个调查还有意义吗?我是不是把类型论和集合论搞混了,把自己弄糊涂了?

我确实认为您原来的 MyTuples 违反了 DRY 原则,Fyodor 建议使用通用记录类型来代替是最好的方法:

type Shared = { a: string; b: string; c: string }

type MyTuples =
    | One of Shared
    | Two of Shared * d: string
    | Three of Shared * e: string * f: int

    with
    member this.Shared =
        match this with
            | One shared -> shared
            | Two (shared, _) -> shared
            | Three (shared, _, _) -> shared

然后您可以共享公共组件,如下所示:

let myTwo = MyTuples.Two ({ a = "1"; b = "2"; c = "3" }, d = "4")
let myThree = Three (myTwo.Shared, e = "5", f = 6)

Does MyTuples violate the DRY pinciple?

我认为没有更多的上下文,这个问题没有明确的答案。

不要重复自己 (DRY) 原则仅适用于重复代码和 context 的情况。在这里,我们没有上下文。 a 是在联合子句中上下文重复的东西,a, b 是重复的东西,是 a, b, c,还是其中的 none?在没有更多上下文的情况下,我认为使用记录的建议是一个不错的建议。但是,如果这些东西确实相关(例如,它们可能表示 3、4、5 维向量),那么您可以在可区分联合内使用匿名记录。例如:

type MyTuples =
    | One of {| a: string; b: string; c: string|}
    | Two of {| a: string; b: string; c: string; d: string |}
    | Three of {| a: string; b: string; c: string; e: string; f: int |}

let one = One {|a="a"; b="b"; c="c"|}

Is there some way show that, say, MyOne is equivalent to MyTuples.One?

是的,您可以定义一个或多个比较函数甚至运算符。

Does this investigation even have any point? Am i mixing up type theory and set theory here and confusing myself?

我不认为这是一项调查。类型旨在帮助您对某些领域进行建模。如果没有域的上下文,这里唯一真正的问题是关于 F# 是否允许扩展现有记录定义的技术问题,答案是否定的。

我不清楚集合论和类型论之间的关系。