我试图过滤特定类型的混合数据类型,比如说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#来说真的很不稳定.看看我如何装饰a和d类型?在我以前的代码中,语言可以解决所有问题.如果我不装饰,我会遇到编译器错误,因为我们真的违背了类型系统的问题.
如果我是你,我会倾向于先做这样的事:
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.toList后Array.map,你会得到一个列表(如果你想要的).