F#:贬低一个受歧视的联盟

Rob*_*Sim 4 f# casting downcast discriminated-union

我有一个有区别的联合类型:

type F =
| A of int
| B of float
Run Code Online (Sandbox Code Playgroud)

假设我有一个已经过滤的F列表,只生成A类对象:

let listOfAs=list.filter (fun f -> match f with | A(f') -> true | _ -> false)
Run Code Online (Sandbox Code Playgroud)

如何处理结果列表F而不需要在我的代码中到处都是模式匹配?编译器不喜欢直接强制转换,例如

list.map (fun f -> int f) listOfAs
Run Code Online (Sandbox Code Playgroud)

Tom*_*cek 9

你不能真正建立有区别的联合值 - 类型与类型F不同int(它不像C联合,它们具有相同的二进制表示).

因此,最简单的解决方案是编写一个函数,该函数接受list<F>并返回list<int>仅包含intAcase 中包装的值.

为此,您可以使用List.choose(而不是List.filter).这允许您指定可以返回的投影None(意味着跳过值)或Some v(意味着返回值v作为结果列表的一部分):

let listOfAs = List.choose (fun f -> 
  match f with 
  | A(f') -> Some f'
  | _ -> None)
Run Code Online (Sandbox Code Playgroud)

  • 是的,它可以是:-)我通常不会在显示代码时这样做,因为它需要一次解释两件事! (3认同)