module AwsAverage; exception NotFound; data Option = None | Some(As); // let db_query student_id course_id = // Raml.tick(1.0); Some 1.0 def Option db_query(Int studentId, Int courseId) = Some(1.0); // let rec append l1 l2 = // match l1 with // | [] -> l2 // | x::xs -> x::(append xs l2) def List append(List l1, List l2) = case l1 { Nil => l2; Cons(x,xs) => Cons(x,append(xs, l2)); }; // let rec partition gt acc l = // match l with // | [] -> acc // | x::xs -> // let (cs,bs,acc) = acc in // let (is_greater,acc') = gt x acc in // if is_greater then // partition gt (cs,x::bs,acc') xs // else // partition gt (x::cs,bs,acc') xs def Triple,List,List> partition(gt)(Triple,List,List> acc, List l) = case l { Nil => acc; Cons(x,xs) => case ass { Triple(cs,bs,acc) => case gt(x, acc) { Pair(isGreater, accP) => if isGreater then partition(Triple(cs,Cons(x,bs,accP)), xs) else partition(Triple(Cons(x,cs),bs,accP), xs); }; }; }; // let rec quicksort gt acc l = match l with // | [] -> ([],acc) // | x::xs -> // let ys, zs, acc' = partition (gt x) ([],[],acc) xs in // let (l1,acc'') = quicksort gt acc' ys in // let (l2,acc''') = quicksort gt acc'' zs in // (append (x :: l1) l2, acc''') def Pair, List> quicksort(gt)(List acc, List l) = case l { Nil => Pair(Nil, acc); Cons(x,xs) => case (partition((Int sid2, List acc) => gt(x,sid2, acc))(Triple(Nil,Nil,acc), xs)) { Triple(ys,zs,accP) => case quicksort(accP,ys) { Pair(l1,accPP) => case quicksort(accPP,zs) { Pair(l2, accPPP) => Pair(append(Cons(x,l1),l2), accPPP); }; }; }; }; // let rec foldl f acc l = // match l with // | [] -> acc // | x::xs -> foldl f (f acc x) xs def A foldlP(f)(A acc, List l) = case l { Nil => acc; Cons(x,xs) => foldlP(f(acc,x),xs); }; // let average_grade student_id course_ids = // let f acc cid = // let (length,sum) = acc in // let grade = match db_query student_id cid with // | Some q -> q // | None -> raise (Not_found (student_id,cid)) // in // (length +. 1.0, sum +. grade) // in // let (length,sum) = foldl f (0.0,0.0) course_ids in // sum /. length def Pair fun(Pair acc, Pair stIdcid) = case stIdcid { Pair(studentId, cid) => case acc { Pair(length, sum) => case db_query(studentId, cid) { Some(g) => Pair(length+1.0, sum + g); None => Pair(length,sum); // throw NotFound; // Exceptions not working! }; }; }; def Float averageGrade(Int studentId, List courseIds) = let (List> list) = map ((Int cid) => Pair(studentId, cid))(courseIds) in case foldlP(fun)(Pair(0.0,0.0), list) { // No partially applied functions, e.g. fun(studentId) // possible! Pair(length,sum) => sum / length; }; // let greater_eq sid1 sid2 course_ids = // (average_grade sid1 course_ids >= average_grade sid2 course_ids, course_ids) def Pair> greaterEq(Int sid1, Int sid2, List courseIds) = Pair(averageGrade(sid1, courseIds) >= averageGrade(sid2, courseIds), courseIds); // let sort_students student_ids course_ids = // let (sorted_sids, acc) = quicksort greater_eq course_ids student_ids in // sorted_sids def List sortStudents(List studentIds, List courseIds) = fst(quicksort(greaterEq)(courseIds,studentIds)); // let rec map f l = // match l with // | [] -> [] // | x::xs -> (f x) :: (map f xs) // let make_table student_ids course_ids = // let rec mk_table sids cids = // match sids with // | [] -> [] // | x::xs -> // let cid_map = // let f cid = // let grade = // match db_query x cid with // | Some q -> q // | None -> raise (Not_found (x,cid)) // in // (cid,grade) // in // map f cids // in // (x,cid_map)::(mk_table xs cids) // in // mk_table student_ids course_ids // let rec find f l = // match l with // | [] -> raise (Not_found (-1,-1)) // | x::xs -> // let (key,value) = x in // if f key then // value // else // find f xs // let lookup sid cid table = // let cid_map = find (fun (id:int) -> id = sid) table in // find (fun (id:int) -> id = cid) cid_map // let average_grade' student_id course_ids table = // let f acc cid = // let (length,sum,table) = acc in // let grade = lookup student_id cid table in // (length +. 1.0, sum +. grade, table) // in // let (length,sum,table') = foldl f (0.0,0.0,table) course_ids in // (sum /. length,table') // let greater_eq' course_ids sid1 sid2 table = // let (grade1, table1) = average_grade' sid1 course_ids table in // let (grade2, table2) = average_grade' sid2 course_ids table1 in // (grade1 >= grade2, table2) // let sort_students_efficient student_ids course_ids = // let (sorted_sids, acc) = quicksort (greater_eq' course_ids) (make_table student_ids course_ids) student_ids in // sorted_sids // let students = [1;2;3;4;5;6] // let courses = [12;13;14;15;16;17;18] // let _ = sort_students students courses { // Main }; // (* let _ = sort_students_efficient students courses *)