F#中的部分匿名记录
Partial anonymous record in F#
我如何键入假设一个函数,该函数获取具有字段 a
和 任何其他字段 的记录?
这个标准 ML 函数是否可以在 F# 中等效?
fun f {a: string, ...} = "Hello" ^ a;
尝试了以下但这些似乎在语法上无效:
let f (r: {|a: string; _|}) = impl;
let g (r: {|a: string; ...|}) = impl;
您可以像这样使用静态解析类型参数实现这种约束:
let inline f< ^T when ^T: (member a: string)> (r: ^T) = ()
f {| a = "yeet" |} // compiles
f {| a = "yeet"; b = "yote" |} // compiles
f {| b = "yote" |} // error
请注意,这 不只是 匿名记录。它适用于任何具有指定签名成员的类型。
我也喜欢将这些东西隐藏在模块后面,并将讨厌的 SRTP 东西提取到活动模式中,如下所示:
module M =
let inline private (|HasName|) x = (^a : (member Name: string) x)
let inline printName (HasName name) = printfn $"{name}"
type Person1 = { Name: string; Age: int }
type Person2 = { Name: string; Age: int; IsFunny: bool }
type Name(name) =
member _.Name = name
let p1 = { Name = "Phillip"; Age = 30 }
let p2 = { Name = "Phillip"; Age = 30; IsFunny = false }
let nm = Name "Phillip"
M.printName p1
M.printName p2
M.printName nm
这样做的好处是可以隐藏有关如何“正确排列”约束的详细信息,并让您可以轻松地在其他要公开的内容中重复使用签名。
我如何键入假设一个函数,该函数获取具有字段 a
和 任何其他字段 的记录?
这个标准 ML 函数是否可以在 F# 中等效?
fun f {a: string, ...} = "Hello" ^ a;
尝试了以下但这些似乎在语法上无效:
let f (r: {|a: string; _|}) = impl;
let g (r: {|a: string; ...|}) = impl;
您可以像这样使用静态解析类型参数实现这种约束:
let inline f< ^T when ^T: (member a: string)> (r: ^T) = ()
f {| a = "yeet" |} // compiles
f {| a = "yeet"; b = "yote" |} // compiles
f {| b = "yote" |} // error
请注意,这 不只是 匿名记录。它适用于任何具有指定签名成员的类型。
我也喜欢将这些东西隐藏在模块后面,并将讨厌的 SRTP 东西提取到活动模式中,如下所示:
module M =
let inline private (|HasName|) x = (^a : (member Name: string) x)
let inline printName (HasName name) = printfn $"{name}"
type Person1 = { Name: string; Age: int }
type Person2 = { Name: string; Age: int; IsFunny: bool }
type Name(name) =
member _.Name = name
let p1 = { Name = "Phillip"; Age = 30 }
let p2 = { Name = "Phillip"; Age = 30; IsFunny = false }
let nm = Name "Phillip"
M.printName p1
M.printName p2
M.printName nm
这样做的好处是可以隐藏有关如何“正确排列”约束的详细信息,并让您可以轻松地在其他要公开的内容中重复使用签名。