diff --git a/sml/week4/hw3.sml b/sml/week4/hw3.sml index 76e983f..6386fb5 100644 --- a/sml/week4/hw3.sml +++ b/sml/week4/hw3.sml @@ -1,6 +1,8 @@ use "operators.sml"; use "list.sml"; +exception NoAnswer + fun first str = String.sub (str, 0) val only_capitals = filter (first >> Char.isUpper) @@ -25,4 +27,25 @@ fun longest_string_helper f = val longest_capitalized = only_capitals >> longest_string2 -val rev_string = String.explode >> List.rev >> String.implode \ No newline at end of file +val rev_string = String.explode >> List.rev >> String.implode + +fun first_answer f lst = + case lst of + [] => raise NoAnswer + | head :: tail => + case f head of + NONE => first_answer f tail + | SOME answer => answer + +fun all_answers (f: ('a -> 'b list option)) lst: 'b list option = + let + fun collect lst acc = + case lst of + [] => SOME acc + | head :: tail => + case f head of + NONE => NONE + | SOME lst => collect tail (acc @ lst) + in + collect lst [] + end \ No newline at end of file diff --git a/sml/week4/hw3_test.sml b/sml/week4/hw3_test.sml index 3ac1460..6c15dff 100644 --- a/sml/week4/hw3_test.sml +++ b/sml/week4/hw3_test.sml @@ -44,5 +44,47 @@ val () = $ rev_string "string" = "gnirts" $ "rev_string: reverses string" +val NONE = + first_answer (fn elm => NONE) [] + handle NoAnswer => + assert true "first_answer: rises on on empty lst" + |> (fn _ => NONE) + +val NONE = + first_answer (fn elm => NONE) ["elm"] + handle NoAnswer => + assert true "first_answer: rises on miss" + |> (fn _ => NONE) + +val () = + assert + $ first_answer (fn elm => SOME elm) ["elm"] = "elm" + $ "first_answer: returns first answer" + + +val () = + assert + $ first_answer + (fn elm => if elm = "second" then SOME elm else NONE) + ["elm", "second"] = "second" + $ "first_answer: returns some answer" + +val () = + assert + $ all_answers (fn elm => SOME elm) [] = SOME [] + $ "all_answers: returns SOME [] on []" + +val () = + assert + $ all_answers (fn elm => SOME [elm]) ["a", "b"] = SOME ["a", "b"] + $ "all_answers: returns all answers" + +val () = + assert + $ all_answers + (fn elm => if elm = "a" then SOME [elm] else NONE) + ["a", "b"] = NONE + $ "all_answers: NONE on at least one NONE" + val () = complete () \ No newline at end of file diff --git a/sml/week4/list.sml b/sml/week4/list.sml index f5c4804..5173380 100644 --- a/sml/week4/list.sml +++ b/sml/week4/list.sml @@ -2,6 +2,8 @@ use "operators.sml"; fun cons head tail = head :: tail +fun append a b = a @ b + fun foldl f acc lst = case lst of [] => acc @@ -9,6 +11,7 @@ fun foldl f acc lst = fun reverse lst = foldl cons [] lst +(* wrong implementation *) fun foldr f acc = foldl f acc >> reverse fun map f = foldr (f >> cons) []