diff --git a/sml/week3_2020/assigment.pdf b/sml/week3_2020/assigment.pdf new file mode 100644 index 0000000..b9a50ed Binary files /dev/null and b/sml/week3_2020/assigment.pdf differ diff --git a/sml/week3_2020/json.sml b/sml/week3_2020/json.sml new file mode 100644 index 0000000..30894b6 --- /dev/null +++ b/sml/week3_2020/json.sml @@ -0,0 +1,23 @@ +use "operators.sml"; +use "list.sml"; + +exception NotSorted + +val strcmp = String.compare + +type count_occurrences = (string list * exn) -> (string * int) list +val rec count_occurrences = fn (strs, exn) => + let + fun repetitons str lst reps order = + case lst of + [] => [(str, reps)] + | head :: tail => + case strcmp (str, head) of + EQUAL => repetitons str tail (reps + 1) order + | new_order => + if order <> EQUAL andalso new_order <> order + then raise exn + else [(str, reps)] @ repetitons head tail 1 new_order + in + case strs of [] => [] | head :: tail => repetitons head tail 1 EQUAL + end \ No newline at end of file diff --git a/sml/week3_2020/json_test.sml b/sml/week3_2020/json_test.sml new file mode 100644 index 0000000..4bbf0df --- /dev/null +++ b/sml/week3_2020/json_test.sml @@ -0,0 +1,47 @@ +use "test.sml"; +use "operators.sml"; +use "json.sml"; + +(* val () = + assert + $ repeatings "a" ["a", "a", "b"] (0, [], EQUAL) = (2, ["b"], LESS) + $ "repetings 1" + +val () = + assert + $ repeatings "c" ["a", "a", "b"] (0, [], EQUAL) = (0, ["a", "a", "b"], GREATER) + $ "repetings 2" *) + +val () = + assert + $ count_occurrences ([], NotSorted) = [] + $ "count_occurrences: [] = []" + +val () = + assert + $ count_occurrences (["a"], NotSorted) = [("a", 1)] + $ "count_occurrences: ['a'] = [('a', 1)]" + +val () = + assert + $ count_occurrences (["a", "b"], NotSorted) = [("a", 1), ("b", 1)] + $ "count_occurrences: ['a', 'b'] = [('a', 1), ('b', 1)]" + + +val () = + assert + $ count_occurrences (["a", "a", "b"], NotSorted) = [("a", 2), ("b", 1)] + $ "count_occurrences: ['a', 'a', 'b'] = [('a', 2), ('b', 1)]" + +val () = + assert + $ count_occurrences (["b", "a", "a"], NotSorted) = [("b", 1), ("a", 2)] + $ "count_occurrences: ['b', 'a', 'a'] = [('b', 1), ('a', 2)]" + +val [] = + count_occurrences (["a", "a", "b", "a"], NotSorted) + handle NotSorted => + assert true "count_occurrences: raises on unsorted list" + |> (fn _ => []) + +val () = complete () \ No newline at end of file diff --git a/sml/week3_2020/list.sml b/sml/week3_2020/list.sml new file mode 100644 index 0000000..9a29c86 --- /dev/null +++ b/sml/week3_2020/list.sml @@ -0,0 +1,31 @@ +use "operators.sml"; + +fun cons head tail = head :: tail + +fun foldl f acc lst = + case lst of + [] => acc + | head :: tail => foldl f (f head acc) tail + +fun reverse lst = foldl cons [] lst + +fun foldr f acc = foldl f acc >> reverse + +fun map f = foldr (f >> cons) [] + +fun filter predicate lst = + let + fun f elm acc = if predicate elm then elm :: acc else acc + in + foldr f [] lst + end + + +fun empty lst = lst = [] + +(* not efficient but works *) +fun exists elem lst = + lst + |> filter (fn needle => elem = needle) + |> empty + |> not \ No newline at end of file diff --git a/sml/week3_2020/operators.sml b/sml/week3_2020/operators.sml new file mode 100644 index 0000000..1df007a --- /dev/null +++ b/sml/week3_2020/operators.sml @@ -0,0 +1,21 @@ +(* + Pipe operator. + Simply to write code like "data |> fun" instead "fun data". + Then you can "pipe" results to functions via partial application: + + fun square a b = a * b + fun sum a b = a + b + + 10 |> sum 10 |> square 2 // 40 +*) +fun op |> (x, f) = f x + +(* apply operator *) +fun op $ (f, x) = f x + +(* composition operator *) +fun op >> (f, g) x = g(f(x)) + +infix |> +infix $ +infix >> \ No newline at end of file diff --git a/sml/week3_2020/test.sml b/sml/week3_2020/test.sml new file mode 100644 index 0000000..8a4f8d4 --- /dev/null +++ b/sml/week3_2020/test.sml @@ -0,0 +1,17 @@ +fun assert condition message = + if condition + then + print (message ^ "\n") + else + let + val () = print ("Assert error: " ^ message ^ "\n") + in + OS.Process.exit OS.Process.failure + end + +fun complete () = + let + val () = print "All tests passed!" + in + OS.Process.exit OS.Process.success + end \ No newline at end of file