f#如何过滤特定类型的混合数据类型

nik*_*nik 0 f#

我试图过滤特定类型的混合数据类型,比如说float(理想情况下这会是动态的)

这是我的例子:

let testobj = [8.0 , 1.0, "bla" ; 8.0 , 1.0, "bla"]

let testfun data = data |> List.filter (fun a -> 
      match a.GetType() with 
      | float -> a
      | _ -> 0.0)
Run Code Online (Sandbox Code Playgroud)

现在这应该返回[8.0,1.0,0.0; testobj的8.0,1.0,0.0]但是我得到的函数是bool类型的错误

pli*_*nth 11

这不是你想要做的.

认真.

F#希望列表是同类的,并且您的列表不是同类的. float并且string不共享公共基类,因此您不会从中获取列表.

F#要求你做的是为此使用一个有区别的联盟.所以如果你有这种类型:

type Composite =
    | Num of float
    | Str of string
Run Code Online (Sandbox Code Playgroud)

你可以这样定义你的列表:

let data = [ Num(8.0); Num(1.0); Str("bla"); Num(8.0); Num(1.0); Str("bla") ]
Run Code Online (Sandbox Code Playgroud)

从那里你可以在类型上进行模式匹配,你的函数看起来像这样:

let testfun d = d |> List.map (fun a ->
    match a with
    | Num x -> a
    | _ -> Num(0.0) )

data|> testfun |> printfn "%A"
Run Code Online (Sandbox Code Playgroud)

输出将是:

 [Num 8.0; Num 1.0; Num 0.0; Num 8.0 ; Num 1.0 ; Num 0.0;]
Run Code Online (Sandbox Code Playgroud)

如果您想要浮点数而不是复合材料,请执行以下操作:

let testfun1 d = d |> List.map (fun a ->
    match a with
    | Num x -> x
    | _ -> 0.0 )
Run Code Online (Sandbox Code Playgroud)

脱落复合型.并且该代码中的所有内容(我指的是所有内容)都是强类型和类型安全的.

从现实维护的角度来看,我会_在匹配中避开这种情况,而是使用我的所有类型,推断如果我扩展Composite以包含另一种类型,我希望编译器对我尖叫并查看每个函数使用它而不是默默地假设0.0或Num(0.0)真的是我想要的.

例如,如果我将整数添加到该类型,如果我想要对复合列表的内容求和,这将完全是错误的.

鉴于你对弱类型数据集感到困惑/顽固,那么你想要这样的东西:

let testfun2 d = d |> Array.map (fun (a:Object) ->
    match a with
    | :? float as x -> x
    | _ -> 0.0
    )

let data:Object[] = [|8.0; 1.0; "bla"; 8.0; 1.0; "bla"|]
data |> testfun2 |> printfn "%A"
Run Code Online (Sandbox Code Playgroud)

这将打印您所期望的.请注意,我使用的是正确的Array语法而不是 list语法.

然而,这对F#来说真的很不稳定.看看我如何装饰ad类型?在我以前的代码中,语言可以解决所有问题.如果我不装饰,我会遇到编译器错误,因为我们真的违背了类型系统的问题.

如果是你,我会倾向于先做这样的事:

let recast d = d |> Array.map (fun (a:Object) ->
    match a with
    | :? float as x -> Num x
    | :? string as x -> Str x
    | _ -> raise (ArgumentException("that was unexpected: " + a.GetType().Name))
    )
Run Code Online (Sandbox Code Playgroud)

这把它变成了一个复合数组,现在类型很强.如果你钉在|> Array.toListArray.map,你会得到一个列表(如果你想要的).