【问题标题】:F# generic function filter list of discriminated unionsF#泛型函数过滤器列表区分联合
【发布时间】:2016-03-11 06:57:02
【问题描述】:

F# 新手问题。 我有一个受歧视的工会列表,例如:

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|Type2|Type3)?

【问题讨论】:

  • 您的问题已经解决了吗?

标签: generics filter f# unions


【解决方案1】:

我的方法可能只是使用List.chooseSeq.choose。它比filter/map 具有优势,因为您只需要执行一次模式匹配,并且比fold 简洁得多。

lst1 
|> List.choose 
    (function
     |T1 res -> Some res
     |_ > None)

choose 类似于地图和过滤器的组合,它为结果为Some 的每个元素返回f(x),并忽略所有为None 的元素。在此示例中,返回类型为 Type1 list


不可能基于特定的联合情况对函数进行参数化,这是因为特定的联合情况本身不是类型,它们只是联合类型的构造函数。 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 类型提供访问器函数(例如static member t1 = function T1 t -&gt; Some t | _ -&gt; None)然后将它们用作List.choose 的参数(例如List.choose Union1.t1)来很好地对其进行编码。
  • 行得通!但我首先必须声明 Type1 .. Type3 ,然后是联合构造函数 T1 .. T3,然后才将静态“匹配”函数添加到类型 Type1 .. Type2 中。对吗?
  • @RobF 我认为你的问题的答案是肯定的,但我已经用这种结构的一个例子更新了我的答案,希望能起到澄清作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-24
  • 2016-11-13
  • 2021-12-22
  • 2020-08-22
  • 2011-11-04
相关资源
最近更新 更多