f#如何为特定类型筛选混合数据类型

f#如何为特定类型筛选混合数据类型,f#,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) 现在testobj应该返回[8.0,1

我试图为特定类型过滤混合数据类型,比如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)

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

这不是您想要做的

真的

F#希望列表是同质的,而您的列表不是同质的
float
string
不共享公共基类,因此无法从中获取列表

F#想让你做的是利用一个歧视性的联盟。因此,如果您有这种类型:

type Composite =
    | Num of float
    | Str of string
您可以这样定义列表:

let data = [ Num(8.0); Num(1.0); Str("bla"); Num(8.0); Num(1.0); Str("bla") ]
let testfun d = d |> List.map (fun a ->
    match a with
    | Num x -> a
    | _ -> Num(0.0) )

data|> testfun |> printfn "%A"
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"
从那里,您可以对类型进行模式匹配,您的函数如下所示:

let data = [ Num(8.0); Num(1.0); Str("bla"); Num(8.0); Num(1.0); Str("bla") ]
let testfun d = d |> List.map (fun a ->
    match a with
    | Num x -> a
    | _ -> Num(0.0) )

data|> testfun |> printfn "%A"
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"
输出将是:

 [Num 8.0; Num 1.0; Num 0.0; Num 8.0 ; Num 1.0 ; Num 0.0;]
如果希望在末尾使用浮动而不是合成,请执行以下操作:

let testfun1 d = d |> List.map (fun a ->
    match a with
    | Num x -> x
    | _ -> 0.0 )
这是一个组合类型。代码中的所有内容(我指的是所有内容)都是类型强且类型安全的

从实际维护的角度来看,我会避免匹配中的
\uucode>情况,而是使用我的所有类型,理由是如果我扩展Composite以包含另一个类型,我会希望编译器对我尖叫并查看使用它的每个函数,而不是默默地假设为0.0或Num(0.0)这正是我想要的

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

假设您被弱类型的数据集所困扰,那么您需要这样的东西:

let data = [ Num(8.0); Num(1.0); Str("bla"); Num(8.0); Num(1.0); Str("bla") ]
let testfun d = d |> List.map (fun a ->
    match a with
    | Num x -> a
    | _ -> Num(0.0) )

data|> testfun |> printfn "%A"
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"
它将打印出您期望的内容。请注意,我使用的是正确的数组语法和而不是列表语法

然而对于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))
    )

这将把它转换成一个复合数组,现在它的类型是strong。如果在
Array.map
之后加上
|>Array.toList
,您会得到一个列表(如果您需要的话)。

testobj
属于
(float*float*string)list类型。这就是你需要的,或者它应该是一个任何类型的对象列表(
obj list
)?它实际上是对象[,],我想要的是除了第一行和前两列以外的双倍体谢谢。问题是我从数据库中获取了一个对象[,],因为它包含1个标题行、两个字符串列和rest double,我只想筛选double。上面声明的是一个元组列表。你有对象数组吗?是的,对象[9000500],元组只是一个如何过滤的测试