提问人:rasx 提问时间:12/31/2021 更新时间:1/1/2022 访问量:120
在可区分的联合中共享元组类型
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")
我的旧数学书告诉我那里有等价性。
是否违反 DRY pinciple?有没有某种方式表明,比如说,等价于?这项调查有什么意义吗?我是不是把类型论和集合论混为一谈,把自己弄糊涂了?MyTuples
MyOne
MyTuples.One
答:
我确实认为您的原始记录违反了 DRY 原则,而 Fyodor 建议使用通用记录类型代替是最好的方法:MyTuples
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)
评论
&
match
MyTuples 是否违反了 DRY pinciple?
我认为如果没有更多的背景,这个问题就没有明确的答案。
不要重复自己 (DRY) 原则仅适用于代码和上下文都重复的情况。在这里,我们没有上下文。在你的联合子句中,在上下文中重复的东西,是重复的东西,是,还是没有?如果没有更多的上下文,我认为使用记录的建议是一个很好的建议。但是,如果这些东西确实相关(例如,它们可能表示 3、4、5 维向量),那么您可以在有区别的联合中使用匿名记录。例如:a
a, b
a, b, c
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"|}
有没有办法证明,比如说,MyOne 等同于 MyTuples.One?
是的,您可以定义一个或多个比较函数甚至运算符。
这项调查有什么意义吗?我是不是把类型论和集合论混为一谈,把自己弄糊涂了?
我不认为这是一项调查。类型旨在帮助您对某些域进行建模。如果没有域的上下文,这里唯一的问题就是一个技术问题,即 F# 是否允许扩展现有的记录定义,答案是否定的。
我不清楚集合和类型理论是如何相关的。
评论
{| abc with d="d" |}
let abc = {|a="a"; b="b"; c="c"|}
type TwoVector = {x: float; y: float}
type ThreeVector = {x: float; y: float; z: float}
type Vector = | TwoVector of TwoVector | ThreeVector of ThreeVector
评论