来自查询表达式的F#强制类型

时间:2015-03-10 02:47:13

标签: f#

我有一个表单的查询表达式:

let result = query { for row in context.Table do
                     where (row.id = 111111)
                     select (row.col1,row.col2,row.col3) }

Result返回IQueryable类型的值< Nullable< float> * Nullable< float> * Nullable< float>>。我希望它返回seq< float> * seq< float> * seq< float>。

我可以尝试改变它:

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&lt; Nullable&lt; float&gt; * Nullable&lt; float&gt; * Nullable&lt; float&gt;&gt; - &GT; SEQ&LT;浮动&GT; * seq&lt; float&gt; * seq&lt; float&gt; 但给定IQueryable&lt; Nullable&lt; float&gt; * Nullable&lt; float&gt; * Nullable&lt; float&gt;&gt; - &GT; SEQ&LT;'一&GT;
类型'seq&lt; float&gt; * seq&lt; float&gt; * seq&lt; float&gt;'与“seq&lt;”a&gt;“

类型不匹配

我做错了什么?

编辑:这是我想要做的事情,听起来我的问题可能会给我一个有用的答案,但不是最好的方式来做我想要的。这段代码很难看但有效:

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等模型。

2 个答案:

答案 0 :(得分:2)

这个问题分为两部分:

  • seq<a * b * c>转换为seq<a> * seq<b> * seq<c>List.unzip3Array.unzip3就是这样做的。

  • 摆脱Nullable:它取决于当值为null时你想要发生什么。

    • 如果要为空值返回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
      
    • 如果要忽略存在null的行:

      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
      

答案 1 :(得分:1)

我和马克一样,想知道你要用这​​个来完成什么,但不过,这是你可以做到的一种方式:

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