Skip to content

Instantly share code, notes, and snippets.

@kvalle
Last active December 12, 2015 05:58
Show Gist options
  • Save kvalle/4725568 to your computer and use it in GitHub Desktop.
Save kvalle/4725568 to your computer and use it in GitHub Desktop.
Tests for coursera-pl hw3
fun assert_equals (expected, actual, formatter) =
if expected = actual
then " -- PASS"
else "Expected: '" ^ formatter (expected) ^ "' but got '" ^ formatter (actual) ^ "' -- FAIL"
fun assert_bool_equals(expected, actual) =
if expected = actual then " -- PASS"
else "Expected: " ^ Bool.toString (expected) ^ ", but was: " ^ Bool.toString (actual) ^ " -- FAIL"
fun assert_true (actual) = assert_bool_equals(true, actual)
fun assert_false (actual) = assert_bool_equals(false, actual)
fun assert_raise (f, e) =
(
f();
"Expected: " ^ exnName (e) ^ " to be thrown, but it wasn't -- FAIL"
)
handle e' =>
if exnName e = exnName e' then " -- PASS"
else "Expected: " ^ exnName (e) ^ " to be thrown " ^
"but " ^ exnName (e') ^ " was thrown -- FAIL"
fun assert_equal_fn_outputs(f1, f2, args_list, input_formatter, output_formatter) =
let
fun inner(args_list, errors) =
case (args_list, errors) of
([],[]) => " -- PASS"
| ([], errors) => "Outputs did not match. " ^ (String.concatWith " AND " errors) ^ " -- FAIL"
| (args::rest, errors) =>
let
val out1 = f1(args)
val out2 = f2(args)
in
if out1 = out2 then inner(rest, errors)
else
let val message = "'" ^ input_formatter(args) ^ "' ==> '" ^
output_formatter(out1) ^ "' <> '" ^ output_formatter(out2) ^ "'"
in
inner(rest, message::errors)
end
end
in
inner(args_list, [])
end
val string_formatter = fn s => s
val int_formatter = Int.toString
fun string_list_option_formatter some_list =
case some_list of
NONE => "NONE"
| SOME [] => ""
| SOME (x::[]) => x
| SOME (x::rest) => x ^ ", " ^ string_list_option_formatter(SOME rest)
fun int_list_option_formatter some_list =
case some_list of
NONE => "NONE"
| SOME [] => ""
| SOME (x::[]) => Int.toString(x)
| SOME (x::rest) => Int.toString(x) ^ ", " ^ int_list_option_formatter(SOME rest)
fun string_list_formatter list =
case list of
[] => "EMPTY"
| x::[] => x
| x::rest => x ^ ", " ^ string_list_formatter (rest)
(* hw3 specific below *)
fun valu_formatter v =
case v of
Const n => "Const " ^ Int.toString(n)
| Unit => "Unit"
| Tuple valuList => "Tuple(" ^ (String.concatWith ", " (List.map valu_formatter valuList)) ^ ")"
| Constructor (str, v) => "Constructor(" ^ str ^ ", " ^ valu_formatter(v) ^ ")"
fun binding_formatter (s,v) = s ^ " = " ^ valu_formatter(v)
fun binding_list_option_formatter some_list =
case some_list of
NONE => "NONE"
| SOME list => "SOME ["
^ (String.concatWith ", " (List.map binding_formatter list))
^ "]"
fun type_formatter t =
case t of
Anything => "Anything"
| UnitT => "UnitT"
| IntT => "IntT"
| TupleT ts => "TupleT(" ^(String.concatWith ", " (List.map type_formatter ts)) ^ ")"
| Datatype s => "Datatype(" ^ s ^ ")"
fun type_list_option_formatter list_option =
case list_option of
NONE => "NONE"
| SOME list => "SOME ["
^ (String.concatWith ", " (List.map type_formatter list))
^ "]"
fun type_option_formatter option =
case option of
NONE => "NONE"
| SOME t => "SOME " ^ type_formatter(t)
use "hw3.sml";
use "asserts.sml";
use "formatters.sml";
Control.Print.printDepth := 1024;
(* problem 1 *)
val removes_all_words_not_starting_with_capital =
assert_equals(["Foo", "BAZ"],
only_capitals(["Foo", "bar", "BAZ", "uNF UNF"]),
string_list_formatter)
val empty_list_returns_empty_list =
assert_equals([], only_capitals([]), string_list_formatter)
(* problem 2 *)
val longest_string1_of_empty_list_is_empty_string =
assert_equals("", longest_string1([]), string_formatter)
val longest_string1_returns_the_longest_string =
assert_equals("12345678",
longest_string1(["123", "12345", "12345678", "12"]),
string_formatter)
val longest_string1_returns_first_in_case_of_tie =
assert_equals("foo",
longest_string1(["a","b","foo","c","bar","d"]),
string_formatter)
(* problem 3 *)
val longest_string2_returns_last_in_case_of_tie =
assert_equals("bar",
longest_string2(["a","b","foo","c","bar","d"]),
string_formatter)
(* problem 4 *)
val longest_string3_is_same_as_longest_string1 =
let val inputs = [[""],
["123", "12345", "12345678", "12"],
["a","b","foo","c","bar","d"]]
val out_formatter = string_formatter
val in_formatter = string_list_formatter
in
assert_equal_fn_outputs(longest_string3, longest_string1,
inputs,
in_formatter, out_formatter)
end
val longest_string4_is_same_as_longest_string2 =
let val inputs = [[""],
["123", "12345", "12345678", "12"],
["a","b","foo","c","bar","d"]]
val out_formatter = string_formatter
val in_formatter = string_list_formatter
in
assert_equal_fn_outputs(longest_string4, longest_string2,
inputs,
in_formatter, out_formatter)
end
(* problem 5 *)
val non_capitalized_are_ignored =
assert_equals("Aaa", longest_capitalized(["aaaaaaa", "Aaa"]), string_formatter)
val first_longest_is_returned =
assert_equals("Aaa", longest_capitalized(["aa", "Aaa", "Bbb"]), string_formatter)
val empty_list_returns_empty_string =
assert_equals("", longest_capitalized([]), string_formatter)
(* problem 6 *)
val reverse_of_empty_string_is_unchanged =
assert_equals("", rev_string(""), string_formatter)
val test_reverse_of_non_empty_string =
assert_equals("zab rab oof", rev_string("foo bar baz"), string_formatter)
(* problem 7 *)
val test_empty_args_raises_exception =
assert_raise(
(fn () =>
first_answer (fn x => SOME 1) []),
NoAnswer
)
val exception_is_raised_if_no_args_produce_result =
assert_raise(
(fn () =>
first_answer (fn x => NONE) [1,2,3,4]),
NoAnswer
)
val test_that_first_result_is_returned =
let val even = (fn x => if (x mod 2) = 0 then SOME x else NONE)
in
assert_equals(2,
(first_answer
even
[1,2,3,4]),
int_formatter)
end
(* problem 8 *)
val even_or_none = (fn x => if (x mod 2) = 0 then SOME [x] else NONE)
val test_that_all_answers_returns_SOME_for_empty_list =
assert_equals(SOME [],
all_answers even_or_none [],
int_list_option_formatter)
val test_return_when_all_have_answers =
assert_equals(SOME [2,4],
all_answers even_or_none [2,4],
int_list_option_formatter)
val test_return_when_some_answer_is_NONE =
assert_equals(NONE,
all_answers even_or_none [2,3,4],
int_list_option_formatter)
val test_return_concatinated_answers =
assert_equals(SOME [1,2,1,2,1,2],
all_answers (fn x => SOME [1,2]) [2,3,4],
int_list_option_formatter)
(* problem 9a *)
val test_count_wildcards_on_single_wildcard =
assert_equals(1, count_wildcards(Wildcard), int_formatter)
val test_count_wildcards_on_variable =
assert_equals(0, count_wildcards(Variable "foo"), int_formatter)
val test_count_wildcards_on_nested_pattern =
let val pattern = TupleP([Wildcard,
TupleP([Variable "foo",
Wildcard,
UnitP]),
ConstructorP("bar", Wildcard),
ConstructorP("baz", UnitP),
Wildcard])
in
assert_equals(4, count_wildcards(pattern), int_formatter)
end
(* problem 9b *)
val test_count_wild_and_variable_lengths_on_pattern_with_neighter =
assert_equals(0, count_wild_and_variable_lengths(UnitP), int_formatter)
val test_count_wild_and_variable_lenghts_on_nested_pattern =
let val pattern = TupleP([Wildcard,
TupleP([Variable "foo",
Wildcard,
UnitP]),
Variable "bar"])
in
assert_equals(8, count_wild_and_variable_lengths(pattern), int_formatter)
end
val test_that_count_wild_and_variable_lengths_ignores_constructors =
let val pattern = TupleP([Wildcard,
Variable "foo",
ConstructorP("bar", Wildcard)])
in
assert_equals(5, count_wild_and_variable_lengths(pattern), int_formatter)
end
(* problem 9c *)
val test_count_some_var_in_pattern_without_vars =
assert_equals(0, count_some_var("foo", UnitP), int_formatter)
val test_count_some_var_in_pattern_with_only_other_vars =
assert_equals(0,
count_some_var("foo", TupleP([Variable "bar",
Variable "baz"])),
int_formatter)
val test_count_some_var_in_pattern_with_var_present =
assert_equals(2,
count_some_var("foo", TupleP([Variable "foo",
TupleP([Variable "bar",
Variable "foo"]),
Variable "baz"])),
int_formatter)
(* problem 10 *)
val test_check_pat_on_no_variables_is_true =
assert_true(check_pat(UnitP))
val test_check_pat_on_pattern_with_no_duplicates =
assert_true(check_pat(TupleP([UnitP,
Variable "foo",
ConstructorP ("foo", UnitP), (* should be ignored *)
Variable "bar"])))
val test_check_pat_on_pattern_with_duplicates =
assert_false(check_pat(TupleP([Variable "foo",
Variable "bar",
TupleP([UnitP,
Variable "foo"])])))
(* problem 11 *)
val test_mismatch_between_pattern_and_value =
assert_equals(NONE, match(Const 42, UnitP), binding_list_option_formatter)
val test_matching_pattern_without_variables =
assert_equals(SOME [], match(Const 41, Wildcard), binding_list_option_formatter)
val test_matching_pattern_with_variable_bindings =
assert_equals(SOME [("foo", Tuple([Const 42, Unit])),("bar", Const 100)],
match(Tuple([Unit,
Tuple([Const 42, Unit]),
Const 100,
Constructor("x", Unit)]),
TupleP([UnitP,
Variable "foo",
Variable "bar",
ConstructorP("x", Wildcard)])),
binding_list_option_formatter)
(* problem 12 *)
val test_first_match_with_no_matches =
assert_equals(NONE,
first_match (Const 1) [ConstP 2, UnitP, ConstP 3],
binding_list_option_formatter)
val test_first_match_with_binding =
assert_equals(SOME [("foo", Const 1)],
first_match (Const 1) [ConstP 2, UnitP, Variable "foo", Variable "bar"],
binding_list_option_formatter)
val test_first_match_without_bindings =
assert_equals(SOME [],
first_match (Const 1) [Wildcard, Variable "foo"],
binding_list_option_formatter)
(* challenge problem *)
val test_both_wildcard_and_variable_can_be_anything =
assert_equals(SOME (TupleT [Anything, Anything]),
typecheck_patterns([], [TupleP [Variable("x"),Variable("y")],
TupleP [Wildcard,Wildcard]]),
type_option_formatter)
val test_tuple_more_specific_than_wildcard =
assert_equals(SOME (TupleT [Anything, TupleT [Anything,Anything]]),
typecheck_patterns([], [TupleP [Wildcard, Wildcard],
TupleP [Wildcard, TupleP [Wildcard, Wildcard]]]),
type_option_formatter)
val test_type_check_fail_returns_none =
assert_equals(NONE,
typecheck_patterns([], [UnitP, TupleP [Wildcard, UnitP]]),
type_option_formatter)
val test_type_check_fails_for_undefined_constructors =
assert_equals(NONE,
typecheck_patterns([], [ConstructorP("some_const", Variable "a_variable")]),
type_option_formatter)
val test_type_is_datatype_if_correct_type_is_given_in_constructor =
assert_equals(SOME (Datatype "my_type"),
typecheck_patterns([("my_cons", "my_type", IntT)], [ConstructorP("my_cons", ConstP 13)]),
type_option_formatter)
val test_type_check_fails_for_wrong_type_in_constuctor =
assert_equals(NONE,
typecheck_patterns([("my_cons", "my_type", IntT)], [ConstructorP("my_cons", UnitP)]),
type_option_formatter)
val test_type_of_two_constructors_of_same_datatype =
assert_equals(SOME (Datatype "my_type"),
typecheck_patterns([("int_cons", "my_type", IntT), ("unit_cons", "my_type", UnitT)],
[ConstructorP("int_cons", ConstP 42), ConstructorP("unit_cons", UnitP)]),
type_option_formatter)
val test_type_check_fails_for_two_constructors_of_different_types =
assert_equals(NONE,
typecheck_patterns([("int_cons", "my_type1", IntT), ("unit_cons", "my_type2", UnitT)],
[ConstructorP("int_cons", ConstP 42), ConstructorP("unit_cons", UnitP)]),
type_option_formatter)
val test_variable_is_anything_which_is_more_general_than_IntT =
assert_equals(NONE,
typecheck_patterns([("MyConstructor", "my_datatype", TupleT[Anything,IntT])],
[ConstructorP ("MyConstructor", TupleP[ConstP 4, Variable "x"])]),
type_option_formatter);
val test_type_check_works_for_nested_constructors =
assert_equals(SOME (Datatype "x_type"),
typecheck_patterns ([("x","x_type", Datatype("y_type")),("y","y_type",UnitT)],
[ConstructorP ("x", ConstructorP ("y", UnitP))]),
type_option_formatter)
val test_type_check_works_for_nested_recursive_constructors =
assert_equals(SOME (Datatype "type"),
typecheck_patterns ([("rec_c","type", Datatype("type")), ("nil_c","type",UnitT)],
[ConstructorP ("rec_c", ConstructorP ("nil_c", UnitP))]),
type_option_formatter)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment