F sharp adding lists

162 views Asked by At

how do you convert an obj list to int type. I am trying to add two lists using a map function below but it doesn't work on obj lists.

let query f= 
 seq{
let cmd = new OleDbCommand( "SELECT *  FROM F" );
let conn = new OleDbConnection( @"Provider=Microsoft.ACE.OLEDB.12.0;
Data Source=D:\Users\df\Documents\Vfolio.accdb;
Persist Security Info=False;" )

conn.Open()
let DAdapt = new OleDbDataAdapter("SELECT * FROM F",conn)
let DTab = new DataSet()
let i= DAdapt.Fill(DTab)
let rowCol = DTab.Tables.[0].Rows
let rowCount = rowCol.Count
 for i in 0 .. (rowCount - 1) do
           yield f (rowCol.[i])
   }
 let u= query(fun row -> row.[0])
 let a= List.ofSeq u
 let v=query(fun row -> row.[1])
 let b= List.ofSeq v
 let c = List.map2 (fun x y-> x + y) a b

error msg: The type 'obj' does not support the operator '+'

1

There are 1 answers

1
Fyodor Soikin On BEST ANSWER

Because row.[i] returns type obj, your u and v become seq<obj>, and thus your a and b become type List<obj>, and therefore x and y are inferred to have type obj, and of course, you can't add two objs, which is exactly what the compiler tells you.

If you are sure that row.[0] and row.[1] are numbers of some kind, you should apply the appropriate cast, for example:

let u= query(fun row -> row.[0] :?> int)
let a= List.ofSeq u
let v=query(fun row -> row.[1] :?> int)
let b= List.ofSeq v
let c = List.map2 (fun x y-> x + y) a b

You can apply this cast in other places, too, depending on your taste and requirements, for example:

let c = List.map2 (fun x y-> (x :?> int) + (y :?> int)) a b

Or:

let a= u |> Seq.cast<int> |> List.ofSeq
let b= v |> Seq.cast<int> |> List.ofSeq

But I like the first example best, because it applies the cast at the earliest known point and results in the least amount of extra code.

But beware: if row.[0] turns out to be not an int at runtime, you will get an InvalidCastException.

P.S. In your List.map2 call, you could specify (+) directly instead of wrapping it in an extra lambda:

List.map2 (+) a b

P.P.S Also, it seems that your List.ofSeq calls are wasteful, for Seq also has a map2:

let u = query(fun row -> row.[0] :?> int)
let v = query(fun row -> row.[1] :?> int)
let c = Seq.map2 (+) u v |> List.ofSeq

P.P.P.S Also, have you noticed that each of the two calls to query generates its own DB connection, command, adapter, and dataset? Did you intend this or did you mean to only have one connection and then fetch different columns from the result? If so, you should only call query once:

let c = query( fun row -> (row.[0] :?> int) + (row.[1] :?> int) ) |> List.ofSeq