Generics F#区分并集的通用函数过滤器列表

Generics F#区分并集的通用函数过滤器列表,generics,filter,f#,unions,Generics,Filter,F#,Unions,新手问题。 我有一份受歧视工会的名单,如: type Type1 = { name:string; id: int; } type Type2 = { x: float; y: float;} type Type3 = { x: float; naam:string} type Union1 = | T1 of Type1 | T2 of Type2 | T3 of Type3 let lst1 = [ T1 {name="nnn"; id=3}; T2 {x=

新手问题。 我有一份受歧视工会的名单,如:

type Type1 = { name:string;  id: int;  }
type Type2 = { x: float; y: float;}
type Type3 = { x: float; naam:string}
type Union1 =
    | T1 of Type1
    | T2 of Type2
    | T3 of Type3 
let lst1 = [ T1 {name="nnn";  id=3};  T2 {x=1.1; y=1.3}; T1 {name="naam1";  id=39}; T3{x=0.0; naam="xx"}]; 

//To filter out items of Type1, i do:
let fltT1 (l:list<Union1>) :list<Type1> =
    let rec loop (l:list<Union1>)  (acc:list<Type1>) =
        match l with
        | h::t -> match h with
                   // this is now specific per type
                   | T1{name=n;id=i} -> loop t ({name=n;id=i}::acc)
                   | _ -> loop t acc
        | [] -> acc
    loop l [] |> List.rev 
Type1={name:string;id:int;}
类型Type2={x:float;y:float;}
类型Type3={x:float;naam:string}
第1类=
|类型1的T1
|2型T2
|类型3的T3
设lst1=[T1{name=“nnn”;id=3};T2{x=1.1;y=1.3};T1{name=“naam1”;id=39};T3{x=0.0;naam=“xx”};
//要筛选出类型1的项目,我需要:
让fltT1(l:列表):列表=
让记录循环(l:列表)(acc:列表)=
匹配
|h::t->将h与匹配
//现在这是每种类型的特定值
|T1{name=n;id=i}->循环t({name=n;id=i}::acc)
|_uuT->循环加速
|[]->acc
循环l[]|>List.rev
如何使这样一个函数成为在调用中指定的通用函数
所需的输出类型(Type1 | Type2 | Type3)?

我的方法可能只是使用
列表。选择
顺序。选择
。它比
filter/map
更具优势,因为您只需执行一次模式匹配,而且比
折叠更简洁

lst1 
|> List.choose 
    (function
     |T1 res -> Some res
     |_ > None)
choose
类似于映射和过滤器的组合,它为结果为
Some
的每个元素返回
f(x)
,并忽略其为
None
的所有元素。在本例中,返回类型是
Type1列表


不可能基于特定的联合用例对函数进行参数化,这是因为特定的联合用例本身不是类型,它们只是联合类型的构造函数<在您的示例中,code>T1
不是一种类型,但
Union1
是一种类型。这意味着,在某一点上,需要显式模式匹配来分解它。(请注意,并非所有函数式语言都是如此,Scala的联合用例是用继承建模的,但F#采用Haskell、Ocaml等使用的方法)

正如Fyodor Soikin所提到的,您可以编写一个静态成员或一个函数来检查每种情况,例如:

static member tryAssumeT1 = function 
    |T1 t1 -> Some t1
    | _ -> None
然后可以使用以下语法:

lst1 |> List.choose (tryAssumeT1)

谢谢,又好又短。但似乎我仍然需要编写单独的表达式(函数)来过滤掉Type1、Type2和Type3的项?是否可以创建具有所需类型的参数化函数?您可以通过为您的
Union1
类型提供访问器函数对其进行良好编码,比如
静态成员t1=function t1 t->Some t|uu->None
,然后将它们用作
列表的参数。选择
比如
列表。选择Union1.t1
。这样就行了!但我首先必须声明Type1。。类型3,然后是联合构造函数T1。。T3,并且仅在此之后将静态“匹配”函数添加到类型Type1。。类型2。是吗?@RobF我想你的问题的答案是肯定的,但我已经用这种结构的一个例子更新了我的答案,希望能起到澄清的作用。你的问题已经解决了?