Types 模式匹配F中的解构内联类型测试#

Types 模式匹配F中的解构内联类型测试#,types,syntax,f#,pattern-matching,Types,Syntax,F#,Pattern Matching,有没有一种使用和内联的方法 我可以像这样毫无问题地制作记录模式: 让getName3(a:a)= 匹配 |{name=name}->name 这是一个非常有效的代码: IA型= 摘要ID:字符串 A型= {id:string 名称:string} 接口IA与 成员this.ID=this.ID let getName(a:IA)= 匹配 | :? A作为->A名称 | _ -> "" getName {id=“1234” name=“安德鲁”} //val getName:a:IA->stri

有没有一种使用和内联的方法

我可以像这样毫无问题地制作记录模式:

让getName3(a:a)=
匹配
|{name=name}->name
这是一个非常有效的代码:

IA型=
摘要ID:字符串
A型=
{id:string
名称:string}
接口IA与
成员this.ID=this.ID
let getName(a:IA)=
匹配
| :? A作为->A名称
| _ -> ""
getName
{id=“1234”
name=“安德鲁”}
//val getName:a:IA->string
//val-it:string=“安德鲁”
这就是我要说的:

让getName2(a:IA)=
匹配
| :? 一个({name=name})作为->name//类型测试模式,内联记录模式,甚至可能仍然使用绑定(作为
| _ -> ""
更新

我前面的示例太简单,请使用以下示例:

IA型=
摘要ID:字符串
类型阶段=
|第一步
|第二步
A型=
{id:string
名称:字符串选项
阶段:阶段
}
接口IA与
成员this.ID=this.ID
//这是一个内嵌的“嵌套”模式,我用一个匹配匹配两个选项
让tryGetName(a:a选项)=
匹配
|Some{name=(Some name)}->Some name
|无
//这是一个更复杂的嵌套内联模式
让tryGetStageAndName(a:a选项)=
匹配
|Some{name=(Some name);stage=stage}->Some(stage,name)
|无
//这就是我要寻找的语法:
让tryGetStageAndName2(a:IA选项)=
匹配
//注意一些(:?A as A)->是完全有效的
|Some(:?A({name=(Some name);stage=stage})->Some(stage,name)
|无

我还想澄清一下,我的问题是关于F#语法,而不是特别的场景或围绕特定的
类型A
,因为我们可以做嵌套的内联模式,有没有一种方法可以在类型测试模式之后做模式?

您可以使用活动模式。其思想是将类型测试模式转换为另一种模式,其中包含强制转换的值参与模式,因此我们可以将记录模式嵌套到其中

守则是:

let (|IsA|_|) (a: IA) =
    match a with
    | :? A as a -> Some a
    | _ -> None

let getName2 (a: IA) =
  match a with
  | IsA {name = name} -> name
  | _ -> ""

您可以使用活动模式。其思想是将类型测试模式转换为另一个模式,其中铸造值参与了该模式,因此我们可以将记录模式嵌套到其中

守则是:

let (|IsA|_|) (a: IA) =
    match a with
    | :? A as a -> Some a
    | _ -> None

let getName2 (a: IA) =
  match a with
  | IsA {name = name} -> name
  | _ -> ""

我认为Nghia Bui提出了一个非常好的解决方案。我只是想补充一点,您可能希望使活动模式通用,以处理更多的情况。我已将活动模式案例重命名为
Unbox
,这可能不完全准确。无论如何,请参见以下示例:

type IA =
  abstract ID: string

type A =
  { id: string
    name: string }
  interface IA with
    member this.ID = this.id

type B =
  { id: string
    name: string
    email: string }
  interface IA with
    member this.ID = this.id

let inline (|Unbox|_|)<'T when 'T :> IA> (a: IA) =
    match a with
    | :? 'T as a -> Some a
    | _ -> None

let getName (a: IA) =
  match a with
  | Unbox {A.name = name} -> name
  | Unbox {B.name = name} -> name
  | _ -> ""

getName {id = "123"; name = "A name"}
getName {id = "567"; name = "B name"; email = "abc@123.com"}
IA型=
摘要ID:字符串
A型=
{id:string
名称:string}
接口IA与
成员this.ID=this.ID
B型=
{id:string
名称:string
电子邮件:string}
接口IA与
成员this.ID=this.ID
让内联(| Unbox | |)IA>(a:IA)=
匹配
|:?'T as a->Some a
|无
let getName(a:IA)=
匹配
|Unbox{A.name=name}->name
|Unbox{B.name=name}->name
| _ -> ""
getName{id=“123”;name=“A name”}
getName{id=“567”;name=“B name”电子邮件=“abc@123.com"}

我认为Nghia Bui提出了一个非常好的解决方案。我只想补充一点,您可能希望使活动模式通用,以处理更多的情况。我已将活动模式案例重命名为
Unbox
,这可能不完全准确。无论如何,请参见以下示例:

type IA =
  abstract ID: string

type A =
  { id: string
    name: string }
  interface IA with
    member this.ID = this.id

type B =
  { id: string
    name: string
    email: string }
  interface IA with
    member this.ID = this.id

let inline (|Unbox|_|)<'T when 'T :> IA> (a: IA) =
    match a with
    | :? 'T as a -> Some a
    | _ -> None

let getName (a: IA) =
  match a with
  | Unbox {A.name = name} -> name
  | Unbox {B.name = name} -> name
  | _ -> ""

getName {id = "123"; name = "A name"}
getName {id = "567"; name = "B name"; email = "abc@123.com"}
IA型=
摘要ID:字符串
A型=
{id:string
名称:string}
接口IA与
成员this.ID=this.ID
B型=
{id:string
名称:string
电子邮件:string}
接口IA与
成员this.ID=this.ID
让内联(| Unbox | |)IA>(a:IA)=
匹配
|:?'T as a->Some a
|无
let getName(a:IA)=
匹配
|Unbox{A.name=name}->name
|Unbox{B.name=name}->name
| _ -> ""
getName{id=“123”;name=“A name”}
getName{id=“567”;name=“B name”电子邮件=“abc@123.com"}

这是目前fslang建议中的建议:


此语法尚不存在

这是当前fslang建议中的建议:


此语法尚不存在

有什么原因不能只添加
Name
属性或
GetName()
方法,并将其作为类型定义的一部分而不是单独的函数来实现?这正是接口应该抽象的行为!使用
:?
非常难闻。我强烈建议避免在F#代码中使用类型测试。您应该重新构造代码以避免id必须测试一个
IA
是否是
A
。否则您将如何处理接口?为什么您要处理接口?如果给定两条
A
B
记录,每个记录都有一个
名称
字段,则可以尝试一个有区别的联合
类型AB=A/B
。解构将是stra在模式中向前看,例如,
let getName=function A{name=name}| B{name=name}->name
有什么原因不能只添加
name
属性或
getName()
方法,并将其作为类型定义的一部分而不是单独的函数来实现?这正是接口应该抽象的行为!使用
:?
非常难闻。我强烈建议避免在F#代码中使用类型测试。您应该重新构造代码以避免id必须测试一个
IA
是否是
A
。否则您将如何处理接口?为什么您要处理接口?如果给定两条
A
B
记录,每个记录都有一个
名称
字段,则可以尝试一个有区别的联合
类型AB=A/B
。解构将是stra嗯