F# 从查询表达式转换类型
F# casting type from query expression
我有以下形式的查询表达式:
let result = query { for row in context.Table do
where (row.id = 111111)
select (row.col1,row.col2,row.col3) }
结果return是一个 IQueryable*Nullable*Nullable> 类型的值。我想要它 return seq*seq*seq.
我可以尝试这样修改它:
let result :seq<float>*seq<float>*seq<float> = query { for row in context.Table do
where (row.id = 111111)
select (row.col1,row.col2,row.col3) }
|> Seq.cast
但我得到:
类型不匹配。期待 IQueryable * Nullable * Nullable> -> seq * seq * seq
但给定一个 IQueryable * Nullable * Nullable> -> seq<'a>
类型 'seq<float> * seq<float> * seq<float>' 与类型 'seq<'a>'
不匹配
我做错了什么?
编辑:这是我正在尝试做的事情,听起来我的问题可能会给我一个可用的答案,但不是做我想做的事情的最佳方式。这段代码很丑但有效:
let col1 : seq<float> = query { for row in context.Table do
where (row.id = 111111)
select row.col1 }
|> Seq.cast
let col2 : seq<float> = query { for row in context.Table do
where (row.id = 111111)
select row.col2 }
|> Seq.cast
let model = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(col1,col2)
如果我不转换为浮点数,InterpolateAkima 将无法工作,因为它不接受 Nullable 类型。不过,我不想自己对每一列进行查询。我最终的目标是拥有一个函数,我可以传入 row.id 的任何值并获取 col1、col2、col1、col3 等的模型。
我和 Mark 一样,想知道你想用它完成什么,但是尽管如此,这里有一种方法可以做到这一点:
open System
open System.Linq
// Helpers to recreate your circumstances.
type Context = { id : Int32; col1 : Nullable<Double>; col2 : Nullable<Double>; col3 : Nullable<Double>}
let context = Unchecked.defaultof<IQueryable<Context>>
let result = query { for row in context do
where (row.id = 111111)
select (row.col1,row.col2,row.col3) }
let seqTuple =
result
|> Seq.fold (fun (col1s, col2s, col3s) (col1, col2, col3) ->
(if col1.HasValue then col1.Value :: col1s else col1s),
(if col2.HasValue then col2.Value :: col2s else col2s),
(if col3.HasValue then col3.Value :: col3s else col3s)
) ([], [], [])
|> fun (col1s, col2s, col3s) ->
List.rev col1s,
List.rev col2s,
List.rev col3s
本题分为两部分:
将 seq<a * b * c>
转换为 seq<a> * seq<b> * seq<c>
:List.unzip3
和 Array.unzip3
就是这样做的。
摆脱 Nullable:这取决于您希望在值为 null 时发生什么。
如果你想 return 0 为空值:
let col1, col2, col3 =
query { for row in context.Table do
where (row.id = 111111)
let col1 = if row.col1.HasValue then row.col1.Value else 0.
let col2 = if row.col2.HasValue then row.col2.Value else 0.
let col3 = if row.col3.HasValue then row.col3.Value else 0.
select (col1, col2, col3) }
|> Array.ofSeq
|> Array.unzip3
如果要忽略有空值的行:
let col1, col2, col3 =
query { for row in context.Table do
where (row.id = 111111 && row.col1.HasValue && row.col2.HasValue && row.col3.HasValue)
select (row.col1.Value, row.col2.Value, row.col3.Value) }
|> Array.ofSeq
|> Array.unzip3
我有以下形式的查询表达式:
let result = query { for row in context.Table do
where (row.id = 111111)
select (row.col1,row.col2,row.col3) }
结果return是一个 IQueryable
我可以尝试这样修改它:
let result :seq<float>*seq<float>*seq<float> = query { for row in context.Table do
where (row.id = 111111)
select (row.col1,row.col2,row.col3) }
|> Seq.cast
但我得到:
类型不匹配。期待 IQueryable
类型 'seq<float> * seq<float> * seq<float>' 与类型 'seq<'a>'
我做错了什么?
编辑:这是我正在尝试做的事情,听起来我的问题可能会给我一个可用的答案,但不是做我想做的事情的最佳方式。这段代码很丑但有效:
let col1 : seq<float> = query { for row in context.Table do
where (row.id = 111111)
select row.col1 }
|> Seq.cast
let col2 : seq<float> = query { for row in context.Table do
where (row.id = 111111)
select row.col2 }
|> Seq.cast
let model = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(col1,col2)
如果我不转换为浮点数,InterpolateAkima 将无法工作,因为它不接受 Nullable 类型。不过,我不想自己对每一列进行查询。我最终的目标是拥有一个函数,我可以传入 row.id 的任何值并获取 col1、col2、col1、col3 等的模型。
我和 Mark 一样,想知道你想用它完成什么,但是尽管如此,这里有一种方法可以做到这一点:
open System
open System.Linq
// Helpers to recreate your circumstances.
type Context = { id : Int32; col1 : Nullable<Double>; col2 : Nullable<Double>; col3 : Nullable<Double>}
let context = Unchecked.defaultof<IQueryable<Context>>
let result = query { for row in context do
where (row.id = 111111)
select (row.col1,row.col2,row.col3) }
let seqTuple =
result
|> Seq.fold (fun (col1s, col2s, col3s) (col1, col2, col3) ->
(if col1.HasValue then col1.Value :: col1s else col1s),
(if col2.HasValue then col2.Value :: col2s else col2s),
(if col3.HasValue then col3.Value :: col3s else col3s)
) ([], [], [])
|> fun (col1s, col2s, col3s) ->
List.rev col1s,
List.rev col2s,
List.rev col3s
本题分为两部分:
将
seq<a * b * c>
转换为seq<a> * seq<b> * seq<c>
:List.unzip3
和Array.unzip3
就是这样做的。摆脱 Nullable:这取决于您希望在值为 null 时发生什么。
如果你想 return 0 为空值:
let col1, col2, col3 = query { for row in context.Table do where (row.id = 111111) let col1 = if row.col1.HasValue then row.col1.Value else 0. let col2 = if row.col2.HasValue then row.col2.Value else 0. let col3 = if row.col3.HasValue then row.col3.Value else 0. select (col1, col2, col3) } |> Array.ofSeq |> Array.unzip3
如果要忽略有空值的行:
let col1, col2, col3 = query { for row in context.Table do where (row.id = 111111 && row.col1.HasValue && row.col2.HasValue && row.col3.HasValue) select (row.col1.Value, row.col2.Value, row.col3.Value) } |> Array.ofSeq |> Array.unzip3