在有区别的联合中共享一个元组类型
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")
从类型论的角度来看,myTwo
和 mySharingTwo
不相等,编译器甚至不允许我们在运行时证明这一点。但是从集合论的角度来看,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# 是否允许扩展现有记录定义的技术问题,答案是否定的。
我不清楚集合论和类型论之间的关系。
假设我们有
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")
从类型论的角度来看,myTwo
和 mySharingTwo
不相等,编译器甚至不允许我们在运行时证明这一点。但是从集合论的角度来看,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# 是否允许扩展现有记录定义的技术问题,答案是否定的。
我不清楚集合论和类型论之间的关系。