我有一张地图,其键可能有各种各样的形状(我使用的是"形状"松散地)。为了处理这个问题,我创建了一个有区别的联合(DU):
type AuxDataKey =
| OneString of string
| TwoStrings of string * string
| OneStringInt of string * int
| TwoStringsInt of string * string * int
| OneStringTwoInts of string * int * int
| TwoStringsTwoInts of string * string * int * int
type AuxData = Map<AuxDataKey,AuxDataItem>
可以通过这种方式创建密钥:
let key = AuxDataKey.TwoStringsInt("Vol", ticker, count)
可以从即时创建的密钥中检索信息:
let vols = auxData.[AuxDataKey.TwoStringsInt("Vol", ticker, count)]
这很有效,但我发现它非常麻烦。
另一种方法是创建另一个DU:
type StringInt = String of string | Int of int
然后让Map键成为这些对象的列表。没有必要为地图键创建DU,StringInt
DU更简单。另一方面,这个替代方案看起来不太安全,因为编译器可以接受列表,例如,第一个元素是Int,第二个是String,它不适合AuxDataKey
中的任何一个案例。 DU。我没有在实践中尝试过,因为可能有更好的选择。
是否有惯用的方法来处理must
具有相同类型但具有不同形状的对象?
答案 0 :(得分:5)
你这样做的方式非常惯用。请注意,在引用DU案例时,您不需要为类型名称AuxDataKey
添加前缀,因此您只需编写:
let key = TwoStringsInt("Vol", ticker, count)
有可能将您的类型分解为有意义的部分,但在不知道组成部分的真正含义的情况下很难分辨。这可以摆脱一些重复。例如,只需拉出其中一个字符串,所有情况都有共同点就可以了:
type SubKey =
| A of string
| B of int
| C of string * int
| D of int * int
| E of string * int * int
type AuxDataKey =
{ Key : string
SubKey : SubKey }
其他一些语言具有这样的功能,其中联合案例由类型系统根据返回的不同值自动推断。我相信TypeScript可以做到这一点,而OCaml与其多态变体有类似之处。但是,F#在这方面完全名义上输入,这意味着每个DU案例必须在使用之前进行定义和命名。
答案 1 :(得分:1)
我明白你真正想要的是这样的:
ow2.asm
但是有太多的情况让这感觉像是毫无意义的运动?
你的问题告诉我的方式,你感到被expression problem错误的一面感到痛苦。你有一个完全不同类型的宇宙,你试图在它们的形状中找到一个模式,它将使用(闭合的)区分联合来表示它们是可行的。
F#通过使用该语言的OO功能为您提供了一种简单的切换方式。我之前使用和看过的模式是创建一个开放的类型层次结构,它继承了一个公共基类型(接口或抽象类),并使用部分活动模式扩充它们,这些模式为您提供了一个访问它们的API,感觉很自然。 F#。
type AuxDataKey =
| Vol of string * int
| AnotherKey of string * int * int * string
| ...
并像这样使用它们:
type IAuxDataKey = interface end
type VolKey =
{
arg1: string
arg2: int
}
interface IAuxDataKey
let (|VolKey|_|) (value: IAuxDataKey) =
match value with
| :? VolKey as key -> Some (key.arg1, key.arg2)
| _ -> None
let x = { arg1 = "test"; arg2 = 42 } :> IAuxDataKey
match x with
| VolKey (arg1, arg2) -> printfn "arg1: %s, arg2: %d" arg1 arg2
| _ -> printfn "unknown"
这里只是一个标记界面,但是如果在你的上下文中有意义的话,你可以在那里添加常用成员(例如,如果密钥来自同源,则可以使用解析或创建方法)。
你在这里失去的是能够进行详尽的比赛,你需要全面的案例。但我认为这不是你用例中的一个问题。