diff --git a/sml/week4/assigment.pdf b/sml/week4/assigment.pdf new file mode 100644 index 0000000..154b7ba Binary files /dev/null and b/sml/week4/assigment.pdf differ diff --git a/sml/week4/hw3.sml b/sml/week4/hw3.sml new file mode 100644 index 0000000..76e983f --- /dev/null +++ b/sml/week4/hw3.sml @@ -0,0 +1,28 @@ +use "operators.sml"; +use "list.sml"; + +fun first str = String.sub (str, 0) +val only_capitals = filter (first >> Char.isUpper) + +val size = String.size +fun choose f a b = if f a b then a else b +fun biggest a b = size a > size b +fun bigger_or_equal a b = size a >= size b + +val longest_string1 = foldl (choose biggest) "" + +val longest_string2 = foldl (choose bigger_or_equal) "" + +fun longest_string_helper f = + let + val longest_string3 = longest_string1 + val longest_string4 = longest_string2 + in + if f (0, 0) + then longest_string4 + else longest_string3 + end + +val longest_capitalized = only_capitals >> longest_string2 + +val rev_string = String.explode >> List.rev >> String.implode \ No newline at end of file diff --git a/sml/week4/hw3_test.sml b/sml/week4/hw3_test.sml new file mode 100644 index 0000000..3ac1460 --- /dev/null +++ b/sml/week4/hw3_test.sml @@ -0,0 +1,48 @@ +use "test.sml"; +use "hw3.sml"; + + +val () = + assert + $ only_capitals ["Alpha", "beta"] = ["Alpha"] + $ "only_capitals: filter strings" + +val () = + assert + $ longest_string1 ["alpha", "betta"] = "alpha" + $ "longest_string1: finds longest string" + + +val () = + assert + $ longest_string1 [] = "" + $ "longest_string1: empty syting on empty list" + + +val () = + assert + $ longest_string2 ["alpha", "betta"] = "betta" + $ "longest_string2: on ties it returns the string closest to the end" + +val () = + assert + $ longest_string_helper (op >) ["alpha", "betta"] = "alpha" + $ "longest_string_helper: a > b = longest_string1" + +val () = + assert + $ longest_string_helper (op >=) ["alpha", "betta"] = "betta" + $ "longest_string_helper: a >= b = longest_string2" + +val () = + assert + $ longest_capitalized ["Alpha", "bettaaaa"] = "Alpha" + $ "longest_capitalized: longest capitalized string" + +val () = + assert + $ rev_string "string" = "gnirts" + $ "rev_string: reverses string" + + +val () = complete () \ No newline at end of file diff --git a/sml/week4/list.sml b/sml/week4/list.sml new file mode 100644 index 0000000..f5c4804 --- /dev/null +++ b/sml/week4/list.sml @@ -0,0 +1,30 @@ +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/week4/operators.sml b/sml/week4/operators.sml new file mode 100644 index 0000000..1df007a --- /dev/null +++ b/sml/week4/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/week4/test.sml b/sml/week4/test.sml new file mode 100644 index 0000000..8a4f8d4 --- /dev/null +++ b/sml/week4/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