F# linq2SQL bug or my fail? - linq-to-sql

I already sent the bug to fsbugs#microsoft.com but I also added this link to letter for additional description, code highlighting, discussions and maybe someone find some way to avoid it, because I really like it and want to use.
Code :
<# seq {for a in db.ArchiveAnalogs do
for d in db.Deltas do
if a.ID = d.ID then
if a.Value > d.DeltaLimit then
yield a.Date, d.AboveMessage
else if a.Value < d.DeltaLimit then
yield a.Date, d.BelowMessage}
#> |> query |> Array.ofSeq
Same error messages with update :
<# seq {for a in db.ArchiveAnalogs do
for d in db.Deltas do
if a.ID = d.ID && a.Value > d.DeltaLimit then
yield a.Date, d.AboveMessage
elif a.ID = d.ID && a.Value < d.DeltaLimit then
yield a.Date, d.BelowMessage}
#> |> query |> Array.ofSeq
Error message :
The following construct was used in query but is not recognised by the
F#-to-LINQ query translator: Call
(None,
System.Collections.Generic.IEnumerable1[System.Tuple2[System.DateTime,System.String]]
Singleton[Tuple2](System.Tuple2[System.DateTime,System.String]),
[NewTuple (PropertyGet (Some (a), System.DateTime Date, []),
PropertyGet (Some (d), System.String AboveMessage,
[]))]) This is not a valid query
expression. Check the specification of
permitted queries and consider moving
some of the query out of the quotation
Fixed
Code :
let px =
query <|
<# seq { for cl in db.Dictionaries -> cl }
|> Seq.filter(fun x -> x.ID_Line = l1 || x.ID_Line = l2) #>
|> fun pquery ->
query <|
<# seq { for cd in db.DeltaCompares do
for cl1 in pquery do
if cd.IID1 = cl1.IID then
for cl2 in pquery do
if cd.IID2 = cl2.IID then
yield cl1
yield cl2 } #>
|> List.ofSeq
Same error with update :
let p =
[for cl in db.Dictionaries -> cl]
|> Seq.filter(fun x -> x.ID_Line = l1 || x.ID_Line = l2)
|> fun pquery ->
<# seq { for cd in db.DeltaCompares do
for cl1 in pquery do
for cl2 in pquery do
if cd.IID1 = cl1.IID && cd.IID2 = cl2.IID then
yield cl1, cl2 } #>
|> query |> Seq.collect(fun a -> [fst a; snd a])
Error message :
The following construct was used in query but is not
recognised by the F#-to-LINQ query
translator: Call (None,
System.Collections.Generic.IEnumerable`1[LinqBase.Dictionary]
SingletonDictionary,
[cl1]) This is not a valid query expression. Check the specification of
permitted queries and consider moving
some of the query out of the quotation
fixed
I'm not sure if I do it correct so I also ask you to confirm if this is a bug or not a bug

In the first case, I think the F#-to-LINQ translator may be failing on nested if. Have you tried: (...)
EDIT [Second attempt]: It could also fail because we're using if without else clause. What if you always return something using option type and then filter out None values (there may be a way to make it nicer, but let's start with this):
<# seq {for a in db.ArchiveAnalogs do
for d in db.Deltas do
yield
if a.ID = d.ID && a.Value > d.DeltaLimit then
Some(a.Date, d.AboveMessage)
elif a.ID = d.ID a.Value < d.DeltaLimit then
Some(a.Date, d.BelowMessage)
else None }
#> |> query |> Seq.choose id |> Array.ofSeq
In the second case, it may be failing because of the for nested in if. I'd try this (...)
EDIT: This is actually incorrect use of LINQ (and it wouldn't work in C# too). The problem is that you're collecting some data in memory (pquery) and then passing this as an input to the LINQ (so that it would have to send the data back to the SQL server.
You can try writing it like this (BTW: I think using |> fun x -> is a weird construct when you can write the same thing simply just using let):
let pquery = <# db.Dictionaries
|> Seq.filter(fun x -> x.ID_Line = l1 || x.ID_Line = l2) #>
let px =
<# seq { for cd in db.DeltaCompares do
for p in %pquery do ... } |> query
This is using quotation splicing. For more information about this feature, see my article (search for splicing).

Related

Raising meaningful exceptions in Ocaml

I would like to print a meaningful message when raising a defined exception in OCaml:
type t = A | B of int
exception Wrong of t
Say I have a function
let string_of_t = function
| A -> "A"
| B n -> ("B" ^ (string_of_int n))
Then I would like to have a function
val print_exception : ( 'a -> string ) -> a' exn -> string
so that I can define
let my_raise e =
print_endline ("Error: I got the unexpected value" ^ (print_exception string_of_t e));
raise e [???]
Is there such a function print_exception ?
The problem is not very well-posed (for instance, there is no a' exn type), but I hope my intent is understandable. I've seen that one can use [##deriving sexp] but this looks like some magic outside of the language, and there is probably something easier and within the language.
There are two ways. The first one is using Printexc, the second one would be to match all the exceptions you want to print and print accordingly, something like:
exception Zero of int
exception B of string
let pp ppf = function
| Zero d -> Format.fprintf ppf "Zero of %d" d
| B s -> Format.fprintf ppf "B of %s" s
| Not_found -> Format.fprintf ppf "Not found"
| _ -> Format.fprintf ppf "Your exception is in another castle"
let f n d = if d = 0 then raise (Zero d) else n / d
let () =
let n, d = (10, 0) in
try Format.printf "%d/%d is %d#." n d (f n d)
with e ->
Format.eprintf "%a#." pp e;
Format.eprintf "%s#." (Printexc.to_string e)
Will give
❯ ./exc
Zero of 0
Exc.Zero(0)
Combining the two seems to be the best solution to be able to customise some displays and let all the others be a default one:
let pp ppf = function
| Zero d -> Format.fprintf ppf "Zero of %d" d
| e -> Format.fprintf ppf "%s" (Printexc.to_string e)
In OCaml we don't have (yet) modular implicits so unless you use [##derive ...] you need to use one of the two solutions.
As a side-note, exceptions can be caught in a pattern matching:
let () =
let n, d = (10, 0) in
match f n d with
| r -> Format.printf "%d/%d is %d#." n d r
| exception e ->
Format.eprintf "%a#." pp e;
Format.eprintf "%s#." (Printexc.to_string e)
It does semantically the same as what I wrote before but it's better for call stacks (if I'm not mistaken)
[EDIT] Looks like I forgot a third solution, see #octachron's answer
If you want to log a meaningful message before raising, it seems to me that it might be simpler to combine the logging and exception raising in one function rather than trying to reconstruct an error message from a generic unknown exception after the fact. For instance, the following function
let log_and_raise exn fmt =
Format.kfprintf
(fun ppf -> Format.pp_print_newline ppf (); raise exn)
Format.err_formatter fmt
can be used like this
exception A of int
let test n = log_and_raise (A n) "Raising the exception (A %d)" n
and will raise the exception A n after printing the error message on stderr.

Is it possible to write a recursive grouping function like this in f#

Lets say you had a requirement to group a sequence into a sequence of tuples. Each tuple is a key*seq. So in a sense, the result is a sequence of sequences.
All pretty standard so far.
What if you wanted to further group each sub sequence by some other key? It would be easy enough to map another groupby function onto each element of your sequence of sequences. You would then have a sequence of sequences of sequences.
Starting to get slightly hairy.
What if you wanted to group it even further?
Would it be possible to write a function that can take in a key generating function and an arbitrary sequence, and recursively unwraps the layers and then adds another layer of grouping using the keyFunction?
I suspect the answer is no, because the recursive function would not have a well defined type.
My attempt at this, to further illustrate the idea:
let rec recursiveGrouper keyFunction aSeq =
let first = Seq.head aSeq
match first with
| ((a:'a), _) -> Seq.map (fun (b,(c:seq<'c>)) -> (b, recursiveGrouper keyFunction c)) aSeq
| _ -> Seq.groupBy keyFunction aSeq
EDIT:
Lets add an example of how this might work, it it were possible
type FruitRecord = {Fruit:string; Number:int; SourceFarm:string; Grade:float}
let key1 fr =
fr.Fruit
let key2 fr =
fr.SourceFarm
let key3 fr =
match fr.Grade with
|f when f > 5.0 -> "Very Good"
|f when f > 2.5 -> "Not bad"
|_ -> "Garbage"
Lets say we have a whole bunch of fruit records in a sequence. We want to group them by type of fruit.
One way would be to say
let group1 = fruitRecs |> Seq.groupBy key1
Using our recursive function, this would be
let group1 = recursiveGrouper key1 fruitRecs
Next, lets say we want to group each of the items in the groups of group1 by source farm.
We could say
let group2 =
group1
|> Seq.map (fun (f, s) -> (f, Seq.groupBy key2 s))
Using our recursive function it would be
let group2 = recursiveGrouper key2 group1
And we could go further and group by Grade by saying
let group3 = recursiveGrouper key3 group2
Actually there are some ways to make that recursive function work, using static constraints. Here's a small example:
// If using F# lower than 4.0, use this definition of groupBy
module List =
let groupBy a b = Seq.groupBy a (List.toSeq b) |> Seq.map (fun (a, b) -> a, Seq.toList b) |> Seq.toList
type A = class end // Dummy type
type B = class end // Dummy type
type C =
inherit B
static member ($) (_:C, _:A ) = fun keyFunction -> () // Dummy overload
static member ($) (_:C, _:B ) = fun keyFunction -> () // Dummy overload
static member ($) (_:B, aSeq) = fun keyFunction -> List.groupBy keyFunction aSeq // Ground case overload
static member inline ($) (_:C, aSeq) = fun keyFunction -> List.map (fun (b, c) -> b, (Unchecked.defaultof<C> $ c) keyFunction) aSeq
let inline recursiveGrouper keyFunction aSeq = (Unchecked.defaultof<C> $ aSeq) keyFunction
// Test code
type FruitRecord = {Fruit:string; Number:int; SourceFarm:string; Grade:float}
let key1 fr = fr.Fruit
let key2 fr = fr.SourceFarm
let key3 fr =
match fr.Grade with
|f when f > 5.0 -> "Very Good"
|f when f > 2.5 -> "Not bad"
|_ -> "Garbage"
let fruitRecs = [
{Fruit = "apple" ; Number = 8; SourceFarm = "F"; Grade = 5.5}
{Fruit = "apple" ; Number = 5; SourceFarm = "F"; Grade = 4.5}
{Fruit = "orange"; Number = 8; SourceFarm = "F"; Grade = 5.5}
]
let group1 = recursiveGrouper key1 fruitRecs
let group2 = recursiveGrouper key2 group1
let group3 = recursiveGrouper key3 group2
I don't think you could write it as a recursive function with the sort of constraints you put on yourself - that is:
A tuple 'key * seq<'value> representing the grouping,
A heterogeneous key function (or a collection thereof) - this is what I understand by "group each sub sequence by some other key".
You could make some leeway if you would represent the grouping as an actual tree type (rather than an ad-hoc tree built from tuples) - that way you'd have a well-defined recursive result type to go with your recursive function.
If at that point you would be able to also compromise on the key function to make it homogeneous (worst case - producing a hashcode), you should be able to express what you want within the type system.
You certainly could have a non-recursive grouping function that takes a grouped sequence and puts another level of grouping on top of it - like the one below:
module Seq =
let andGroupBy (projection: 't -> 'newKey) (source: seq<'oldKey * seq<'t>>) =
seq {
for key, sub in source do
let grouped = Seq.groupBy projection sub
for nkey, sub in grouped do
yield (key, nkey), sub
}
Using your FruitRecord example:
values
|> Seq.groupBy key1
|> Seq.andGroupBy key2
|> Seq.andGroupBy key3

OCaml - Save values of recursive function in hashtable

I have this function:
let rec som a b acc =
if a > b then acc else
som (a+1) b (acc+(comb b a));;
And what I am trying to do is to save acc value in a hashtable, so my first try was:
let rec som a b acc =
if a > b then acc else
som (a+1) b (acc+(comb b a)) Hashtbl.add a acc;;
but it does not work... How can I save the values?
This is skeleton, you can try to add you code into it to get what you want. Maybe it will be helpful.
module Key = struct
type t=int
let compare: t->t->int = fun a b -> (* return -1 if a<b, 0 if a=b,and 1 if a>b *)
let equal = (=)
end
module H=Hashtbl.Make(Key)
let som =
let h = H.create () in
let rec f a b acc =
try H.find h acc
with Not_found ->
let ans = (* your evaluation code *) in
H.add h acc ans;
ans
in
f
First, let's take a look at the signature of Hashtbl.add
('a, 'b) Hashtbl.t -> 'a -> 'b -> unit = <fun>
The first argument of the function is an hash table, then you need to create one. To do it, write let h_table = Hashtbl.create 123456;;. And to put it in context your add instruction become HashTbl.add h_table a acc
Next, you can't call this function at the same level of the recursive call. Indeed the function som take three arguments and you will face the following error message, It is applied to too many arguments ....
And as you want to trace the value of acc you need to put it before the recursive call. Doing this can lead you to face some difficulty, then I've added below a hint.
let _ = Printf.printf "a\n" in
let _ = Printf.printf "b\n" in
(1+2)
;;
a
b
- : int = 3

how to get count with linq / linq2sql?

<#[for i in linq.TrueIncidents -> i.RecTime, i.Name ] #> |> query |> Array.ofSeq
How can I get counts of different names ?
just count(Name) where Name = somename...
I think first I must select form here all Names with |> Seq.distinctBy(fun x -> x.Name)
and then make Seq.Count() different selects where Name will be one of names and then union all the selects ... really wierd way.
Or I can use it as object later with closure with int ref counters for each distincted Name...
I understand that my explanation could be some messy , so ask if you can't get it. I want to know is there any way to use Count(Name) where Name = OneOfNames inside closure or linq2sql ?
I can't compile to verify that this works at the moment, but try the following:
<# linq.TrueIncidents
|> Seq.groupBy (fun i -> i.Name)
|> Seq.map (fun (name, is') -> name, Seq.length is') #>
|> query
|> Map.ofSeq
This should give you a Map<string, int> of each name and its respective number of occurrences.

Working with connected tables using F# linq2sql seqences

Teach me how can I improve my F# linq2sql seqences
here I'm using linq2sql but I think that I got problems with it.
and main problem is access by ID here in example I'm making 2 embedded for but I got very scary linq2 sql queries because I don't know is there some additional methods or ways to make it ...
member X.deltaArchive() = // Reacting on delta limits
seq { for a in db.ArchiveAnalogs do
for d in db.Deltas do
if a.ID = d.ID then
if a.Value > d.DeltaLimit then
yield d.AboveMessage
else if a.Value < d.DeltaLimit then
yield d.BelowMessage
} |> Array.ofSeq
So the complete question is : is there any way to make the same without using embedded cycles to find id conformity ?
Thank you.
Added :
using :
<# seq {for a in db.ArchiveAnalogs do
for d in db.Deltas do
if a.ID = d.ID then
if a.Value > d.DeltaLimit then
yield a.Date, d.AboveMessage
else if a.Value < d.DeltaLimit then
yield a.Date, d.BelowMessage}
#> |> query |> Array.ofSeq
got error :
The following construct was used in query but is not recognised by the F#-to-LINQ query translator:
Call (None,
System.Collections.Generic.IEnumerable`1[System.Tuple`2[System.DateTime,System.String]] Singleton[Tuple`2](System.Tuple`2[System.DateTime,System.String]),
[NewTuple (PropertyGet (Some (a), System.DateTime Date, []),
PropertyGet (Some (d), System.String AboveMessage, []))])
This is not a valid query expression. Check the specification of permitted queries and consider moving some of the query out of the quotation
offtopic : I must find solution because this is first google link about "F# linq2sql"
First of all, the snippet you wrote isn't really using LINQ to SQL. You're running the whole processing in memory, because F# doesn't select query operators based on type (as C# does). You need to mark the query explicitly to run it on SQL:
#r "FSharp.PowerPack.Linq.dll"
open Microsoft.FSharp.Linq
<# seq { for a in db.ArchiveAnalogs do ... } #> |> query
An alternative way to write what you want is to use Query.join function (from PowerPack). I believe the following should do the trick:
<# join db.ArchiveAnalogs db.Deltas (fun a -> a.ID) (fun d -> d.ID) (fun a d ->
if a.Value > d.DeltaLimit then
yield d.AboveMessage
else if a.Value < d.DeltaLimit then
yield d.BelowMessage ) #> |> query
(Although, I think that there is really no difference between using join and nested for - If you run this on SQL than it will likely optimize it to join anyway).