这次回顾HW3,主要是Standard ML的头等函数和高阶函数。

课程主页:

https://www.coursera.org/learn/programming-languages/home

B站搬运:

https://www.bilibili.com/video/BV1dL411j7L7

参考资料:

说明

这次的Challenge Problem挺难的,题目也比较难读懂,建议先阅读如下资料:

总的来说,就是给定输入和case表达式,判断输入的类型,具体可以参考测试代码中test13部分。

代码

(* Coursera Programming Languages, Homework 3, Provided Code *)

exception NoAnswer

datatype pattern = Wildcard
		 | Variable of string
		 | UnitP
		 | ConstP of int
		 | TupleP of pattern list
		 | ConstructorP of string * pattern

datatype valu = Const of int
	      | Unit
	      | Tuple of valu list
	      | Constructor of string * valu

fun g f1 f2 p =
    let 
	val r = g f1 f2 
    in
	case p of
	    Wildcard          => f1 ()
	  | Variable x        => f2 x
	  | TupleP ps         => List.foldl (fn (p,i) => (r p) + i) 0 ps
	  | ConstructorP(_,p) => r p
	  | _                 => 0
    end

(**** for the challenge problem only ****)

datatype typ = Anything
	     | UnitT
	     | IntT
	     | TupleT of typ list
	     | Datatype of string

(**** you can put all your code here ****)

(* problem 1 *)
fun only_capitals str_list = 
	List.filter (fn a => Char.isUpper(String.sub(a, 0))) str_list

(* problem 2 *)
fun longest_string1 str_list = 
	let
	  fun helper(str1, str2) = 
		if String.size str1 <= String.size str2
		then str2
		else str1
	in
	  List.foldl helper "" str_list
	end

(* problem 3 *)
fun longest_string2 str_list = 
	let
	  fun helper(str1, str2) = 
		if String.size str1 < String.size str2
		then str2
		else str1
	in
	  List.foldl helper "" str_list
	end

(* problem 4 *)
fun longest_string_helper f str_list = 
	let
	  fun helper(str1, str2) = 
	  	if f((String.size str1), (String.size str2))
		then str1
		else str2
	in
	  List.foldl helper "" str_list
	end

val longest_string3 = longest_string_helper (fn (a, b) => a > b)

val longest_string4 = longest_string_helper (fn (a, b) => a >= b)

(* problem 5 *)
val longest_capitalized = longest_string1 o only_capitals

(* problem 6 *)
val rev_string = String.implode o rev o String.explode

(* problem 7 *)
fun first_answer f list = 
	let
	  fun helper arr = 
	  	case arr of
			 [] => raise NoAnswer
		   | element::arr_rst => 
		   		case element of
					  SOME v => v
					| _ => helper arr_rst
	in
	  helper (List.map f list)
	end

(* problem 8 *)
fun all_answers f list = 
	let
	  fun helper arr = 
	  	case arr of
			 [] => SOME []
		   | element::arr_rst => 
				(
					let
					  val tmp = (helper arr_rst)
					in
					  case tmp of
						 NONE => NONE
					   | SOME res_rst => (
								case element of
								SOME v => SOME (v @ res_rst)
								| _ => NONE
					   	 	  )
					end
				)
	in
	  helper (List.map f list)
	end

(* problem 9 *)
(* a *)
fun sum arr = 
	case arr of
	   [] => 0
	 | a::arr_rst => a + (sum arr_rst)

fun count_wildcards pattern = 
	case pattern of
	   Wildcard => 1
	 | Variable _ => 0
	 | UnitP => 0
	 | ConstP _ => 0
	 | TupleP arr => sum (List.map count_wildcards arr)
	 | ConstructorP (str, p) => count_wildcards p

(* b *)
fun count_wild_and_variable_lengths pattern = 
	case pattern of
	   Wildcard => 1
	 | Variable s => String.size s
	 | UnitP => 0
	 | ConstP _ => 0
	 | TupleP arr => sum (List.map count_wild_and_variable_lengths arr)
	 | ConstructorP (str, p) => count_wild_and_variable_lengths p

(* c *)
fun count_some_var_curry str pattern = 
	case pattern of
	   Wildcard => 0
	 | Variable s => if s = str then 1 else 0
	 | UnitP => 0
	 | ConstP _ => 0
	 | TupleP arr => sum (List.map (count_some_var_curry str) arr)
	 | ConstructorP (str1, p) => count_some_var_curry str p

fun count_some_var(str, pattern) = count_some_var_curry str pattern

(* problem 10 *)
fun fold_helper list = 
	let
	  fun f(a, b) = a @ b
	in
	  List.foldl f [] list
	end

fun get_var_names pattern = 
	case pattern of
	 Variable s => [s]
	 | TupleP arr => fold_helper (List.map get_var_names arr)
	 | ConstructorP (str, p) => get_var_names p
	 | _ => []

fun check_pat pattern = 
	let
	  val arr = get_var_names pattern
	  (* 统计出现次数 *)
	  fun cnt arr x = 
	  	case arr of
			 [] => 0
		   | a::arr_rst => 
				if x = a then (1 + (cnt arr_rst x)) else (cnt arr_rst x)
	  (* 判断出现次数是否大于1 *)
	  fun judge arr = 
	  	case arr of
			 [] => true
		   | a::arr_rst => (a = 1) andalso (judge arr_rst)
	in
	  judge (List.map (cnt arr) arr)
	end

(* problem 11 *)
fun match(valu, pattern) = 
	case (valu, pattern) of
	   (v, Wildcard) => SOME []
	 | (v, Variable s) => SOME [(s, v)]
	 | (Unit, UnitP) => SOME []
	 | (Const s1, ConstP s2) => if s1 = s2 then SOME [] else NONE
	 | (Tuple vs, TupleP ps) => 
	 	(
			if (List.length vs) = (List.length ps)
			(* 需要加括号 *)
			then all_answers match (ListPair.zip(vs, ps))
			else NONE
		 )
	 | (Constructor(s2,v), ConstructorP(s1,p)) => 
	 	(
			if s1 = s2
			then match(v, p)
			else NONE
		 )
	 | _ => NONE

(* problem 12 *)
fun first_match value pattern_list = 
	let
	  fun match_helper valu pattern = match(valu, pattern)
	in
	  SOME (first_answer (match_helper value) pattern_list) handle NoAnswer => NONE
	end

(* problem 13 *)
datatype typ = Anything (* any type of value is okay *)
			 | UnitT (* type for Unit *)
			 | IntT (* type for integers *)
			 | TupleT of typ list (* tuple types *)
			 | Datatype of string (* some named datatype *)
			 | Nothing (* for NONE *)

(* 将两个type合并到最宽松的type *)
fun merge_two_type(typ1, typ2) = 
	case (typ1, typ2) of
	     (_, Nothing) => typ1
	   | (Anything, _) => typ2
	   | (_, Anything) => typ1
	   | (TupleT list1, TupleT list2) =>
		(
			if (List.length list1) = (List.length list2)
			then 
				(* 需要先let *)
				(
					let
					  val tmp = ListPair.zip(list1, list2)
					in
					  TupleT (List.map merge_two_type tmp)
					end
				)
			else Nothing
		)
	   | (IntT, IntT) => IntT
	   | (UnitT, UnitT) => UnitT
	   | (Datatype data_type1, Datatype data_type2) => 
	 	(
			if data_type1 = data_type2
			then Datatype data_type1
			else Nothing
		)
	   | _ => Nothing

(* 获得pattern对应的type *)
fun get_type origin_list current_list pattern_ = 
	let
	  (* pattern为Wildcard或ConstructorP, 特殊处理 *)
	  fun type_helper origin_list current_list pattern_ = 
		case pattern_ of
	   		Wildcard => 
			(
				case current_list of
					[] => Anything
				| (name, data_type, type_)::current_list_rst => (Datatype data_type)
			)
	 	  | ConstructorP (str, p) => 
			(
				case current_list of
					[] => Datatype str
				  | (name, data_type, type_)::current_list_rst => 
					(
						if (name = str) andalso 
							(
								let
								val t1 = get_type origin_list origin_list p
								val t2 = merge_two_type(type_, t1)
								in
								(* 重要, 表示可以兼容 *)
								not (t2 = Nothing)
								end
							)
						then (Datatype data_type)
						else (get_type origin_list current_list_rst pattern_)
					)
			)
	 	  | _ => Nothing
		in
			case pattern_ of
				Wildcard => type_helper origin_list current_list pattern_
			  | Variable s => Anything
			  | UnitP => UnitT
			  | ConstP _ => IntT
			  | TupleP pattern_list => TupleT (List.map (get_type origin_list origin_list) pattern_list)
			  | ConstructorP (str, p) => type_helper origin_list current_list pattern_
		end

(* 获得pattern_list中每个pattern的type *)
fun get_type_list list pattern_list = 
	List.map (get_type list list) pattern_list

(* 合并typelist *)
fun merge_list(list, res) = 
	case list of
	   [] => res
	 | type_::list_rst => merge_list(list_rst, merge_two_type(type_, res))

fun typecheck_patterns(list, pattern_list) = 
	let
	  val type_list = get_type_list list pattern_list
	  val res = merge_list(type_list, Nothing)
	in
	  if res = Nothing
	  then NONE
	  else SOME res
	end

测试

(* Homework3 Simple Test*)
(* These are basic test cases. Passing these tests does not guarantee that your code will pass the actual homework grader *)
(* To run the test, add a new line to the top of this file: use "homeworkname.sml"; *)
(* All the tests should evaluate to true. For example, the REPL should say: val test1 = true : bool *)

use "01_homework-3_hw3provided.sml";

val test1_1 = only_capitals ["A","B","C"] = ["A","B","C"]
val test1_2 = only_capitals ["Abc","abC","C"] = ["Abc","C"]
val test1_3 = only_capitals ["bbc","abC","c"] = []

val test2_1 = longest_string1 ["A","bc","C"] = "bc"
val test2_2 = longest_string1 [] = ""
val test2_3 = longest_string1 ["Ab","bc","C"] = "Ab"

val test3_1 = longest_string2 ["A","bc","C"] = "bc"
val test3_2 = longest_string2 [] = ""
val test3_3 = longest_string2 ["Ab","bc","C"] = "bc"

val test4a_1 = longest_string3 ["A","bc","C"] = "bc"
val test4a_2 = longest_string3 [] = ""
val test4a_3 = longest_string3 ["Ab","bc","C"] = "Ab"

val test4b_1 = longest_string4 ["A","bc","C"] = "bc"
val test4b_2 = longest_string4 [] = ""
val test4b_3 = longest_string4 ["Ab","bc","C"] = "bc"

val test5_1 = longest_capitalized ["A","bc","C"] = "A"
val test5_2 = longest_capitalized ["a","bc","c"] = ""
val test5_3 = longest_capitalized ["A","bc","C","BD"] = "BD"

val test6_1 = rev_string "abc" = "cba"
val test6_2 = rev_string "aba" = "aba"
val test6_3 = rev_string "" = ""

val test7_1 = first_answer (fn x => if x > 3 then SOME x else NONE) [1,2,3,4,5] = 4
val test7_2 = first_answer (fn x => if x > 4 then SOME x else NONE) [1,2,3,4,5] = 5

val test8_1 = all_answers (fn x => if x = 1 then SOME [x] else NONE) [2,3,4,5,6,7] = NONE
val test8_2 = all_answers (fn x => if x > 3 then SOME [x] else NONE) [2,3,4,5,6,7] = NONE
val test8_3 = all_answers (fn x => if x < 6 then SOME [x] else NONE) [2,3,4,5,6,7] = NONE

val test9a_1 = count_wildcards Wildcard = 1

val test9b_1 = count_wild_and_variable_lengths (Variable("a")) = 1

(* val test9c = count_some_var ("x", Variable("x")) = 1

val test10 = check_pat (Variable("x")) = true

val test11 = match (Const(1), UnitP) = NONE

val test12 = first_match Unit [UnitP] = SOME [] *)


(* Homework3 Simple Test*)
(* These are basic test cases. Passing these tests does not guarantee that your code will pass the actual homework grader *)
(* To run the test, add a new line to the top of this file: use "homeworkname.sml"; *)
(* All the tests should evaluate to true. For example, the REPL should say: val test1 = true : bool *)
(* https://www.coursera.org/learn/programming-languages/discussions/forums/c7p3Kij0Eea7jBLLHPwd0w/threads/DA4fpBk2EeevPg7X4ZMqyg *)

val test1 = only_capitals ["A","B","C"] = ["A","B","C"]
val test101 = only_capitals ["a","B","C"] = ["B","C"]
val test102 = only_capitals ["Abc","ABc","abC"] = ["Abc","ABc"]
val test103 = only_capitals ["1AB","?AB","Abc","ABc","abC"] = ["Abc","ABc"]

val test2 = longest_string1 ["A","bc","C"] = "bc"
val test201 = longest_string1 ["A","bc","C", "de"] = "bc"
val test202 = longest_string1 ["A","bc","C", "def"] = "def"

val test3 = longest_string2 ["A","bc","C"] = "bc"
val test301 = longest_string2 ["A","bc","C", "de"] = "de"
val test302 = longest_string2 ["A","bc","C", "def"] = "def"

val test4a = longest_string3 ["A","bc","C"] = "bc"
val test4a1 = longest_string3 ["A","bc","C", "de"] = "bc"
val test4a2 = longest_string3 ["A","bc","C", "def"] = "def"
val test4a3 = longest_string3 ["this","list","has","no","capital","letters"] = "capital"
val test4a4 = longest_string3 ["Alabama","Alaska","Arizona","Arkansas","California","Colorado","Connecticut","Delaware","Florida","Georgia","Hawaii","Idaho","Illinois","Indiana","Iowa","Kansas","Kentucky","Louisiana","Maine","Maryland","massachusetts","Michigan","Minnesota","Mississippi","Missouri","Montana","Nebraska","Nevada","New Hampshire","New Jersey","New Mexico","New York","NorthCarolina","North Dakota","Ohio","Oklahoma","Oregon","Pennsylvania","Rhode Island","southCarolina","South Dakota","Tennessee","Texas","Utah","Vermont","Virginia","Washington","West Virginia","Wisconsin","Wyoming"] = "massachusetts"

val test4b = longest_string4 ["A","B","C"] = "C"
val test4b1 = longest_string4 ["A","bc","C", "de"] = "de"
val test4b2 = longest_string4 ["A","bc","C", "def"] = "def"

val test5 = longest_capitalized ["A","bc","C"] = "A"
val test501 = longest_capitalized [] = ""
val test502 = longest_capitalized ["ab", "a", "b"] = ""

val test6 = rev_string "abc" = "cba"
val test601 = rev_string "" = ""

val test7 = first_answer (fn x => if x > 3 then SOME x else NONE) [1,2,3,4,5] = 4
val test701 = first_answer (fn x => if x > 3 then SOME x else NONE) [4,2,3,5] = 4
val test702 = (first_answer (fn x => if x > 3 then SOME x else NONE) [1,2,3] ; false) handle NoAnswer => true
val test7022 = (first_answer (fn x => if x > 3 then SOME x else NONE) [1,2,3] ; false) handle OtherException => true
val test703 = first_answer (fn x => if x > 3 then SOME x else NONE) [1,2,3,4,2] = 4

val test8 = all_answers (fn x => if x = 1 then SOME [x] else NONE) [2,3,4,5,6,7] = NONE
val test801 = all_answers (fn x => if x = 2 then SOME [x] else NONE) [3,2,4,5,6,7] = NONE
val test802 = all_answers (fn x => if x mod 2 = 0 then SOME [x] else NONE) [2,4,5,6,8] = NONE
val test803 = all_answers (fn x => if x mod 2 = 0 then SOME [x] else NONE) [2,4,6,8] = SOME [2,4,6,8]
val test804 = all_answers (fn x => if x mod 2 = 0 then SOME [x, x + 1] else NONE) [2,4,6,8] = SOME [2,3,4,5,6,7,8,9]
val test805 = all_answers (fn x => if x mod 2 = 0 then SOME [] else NONE) [2,4,6,8] = SOME []
val test806 = all_answers (fn x => if x mod 2 = 0 then SOME [x] else NONE) [] = SOME []

val test9a = count_wildcards Wildcard = 1
val test9a01 = count_wildcards (Variable "str") = 0
val test9a02 = count_wildcards (TupleP [Wildcard, ConstP 12, Wildcard]) = 2
val test9a03 = count_wildcards (ConstructorP("pattern", (TupleP [Wildcard, ConstP 12, Wildcard]))) = 2

val test9b = count_wild_and_variable_lengths (Variable("a")) = 1
val test9b01 = count_wild_and_variable_lengths Wildcard = 1
val test9b02 = count_wild_and_variable_lengths (TupleP [Wildcard, ConstP 12, Wildcard]) = 2
val test9b03 = count_wild_and_variable_lengths (TupleP [Wildcard, Variable "str", Wildcard]) = 5
val test9b04 = count_wild_and_variable_lengths (TupleP [Wildcard, Variable "str", Wildcard, Variable "str2"]) = 9
val test9b05 = count_wild_and_variable_lengths (ConstructorP("pattern", (TupleP [Wildcard, ConstP 12, Wildcard]))) = 2
val test9b06 = count_wild_and_variable_lengths (ConstructorP("pattern", (TupleP [Wildcard, Variable "str", Wildcard]))) = 5

val test9c = count_some_var ("x", Variable("x")) = 1
val test9c01 = count_some_var ("x", (TupleP [Wildcard, ConstP 12, Wildcard])) = 0
val test9c02 = count_some_var ("x", (TupleP [Wildcard, Variable "str", Wildcard])) = 0
val test9c03 = count_some_var ("x", (TupleP [Wildcard, Variable "x", Wildcard])) = 1
val test9c04 = count_some_var ("x", (TupleP [Wildcard, Variable "x", Wildcard, Variable "x"])) = 2
val test9c05 = count_some_var ("x", (ConstructorP("pattern", (TupleP [Wildcard, Variable "x", Wildcard])))) = 1
val test9c06 = count_some_var ("x", (ConstructorP("x", (TupleP [Wildcard, Variable "x", Wildcard])))) = 1

val test10 = check_pat (Variable("x")) = true
val test1001 = check_pat (TupleP [Wildcard, Variable "x", Wildcard]) = true
val test1002 = check_pat (TupleP [Wildcard, Variable "x", Variable "y"]) = true
val test1003 = check_pat (TupleP [Wildcard, Variable "x", Variable "x"]) = false
val test1004 = check_pat (ConstructorP("x", (TupleP [Wildcard, Variable "x", Wildcard]))) = true
val test1005 = check_pat (ConstructorP("x", (TupleP [Wildcard, Variable "x", ConstructorP("y", Variable "y")]))) = true
val test1006 = check_pat (ConstructorP("x", (TupleP [Wildcard, Variable "x", ConstructorP("y", Variable "x")]))) = false
val test1007 = check_pat (ConstructorP("x", (TupleP [Wildcard, Variable "x", ConstructorP("y", TupleP [Variable "y"])]))) = true
val test1008 = check_pat (ConstructorP("x", (TupleP [Wildcard, Variable "x", ConstructorP("y", TupleP [Variable "z"])]))) = true
val test1009 = check_pat (ConstructorP("x", (TupleP [Wildcard, Variable "x", ConstructorP("y", TupleP [Variable "x"])]))) = false
val test1010 = check_pat (ConstructorP("x", (ConstructorP("y", TupleP [Variable "x", Variable "y"])))) = true
val test1011 = check_pat (ConstructorP("x", (ConstructorP("y", TupleP [Variable "x", Variable "x"])))) = false
val test1012 = check_pat (TupleP [Wildcard, Variable "x", TupleP [Variable "y"]]) = true

val test11 = match (Const(1), UnitP) = NONE
val test1101 = match (Const(1), ConstP 1) = SOME []
val test1102 = match (Const(1), Variable "s") = SOME [("s", Const(1))]
val test1103 = match (Const(1), TupleP [Wildcard]) = NONE
val test1104 = match (Const(1), TupleP [ConstP 1]) = NONE
val test1105 = match (Tuple [Unit], TupleP [UnitP]) = SOME []
val test1106 = match (Tuple [Tuple [Unit]], TupleP [TupleP[UnitP]]) = SOME []
val test1107 = match (Tuple [Tuple [Unit]], TupleP [TupleP[UnitP, Variable "x"]]) = NONE
val test1108 = match (Tuple [Const(1), Tuple [Unit]], TupleP [ConstP 1, TupleP[UnitP]]) = SOME []
val test1109 = match (Tuple [Const(1), Tuple [Unit, Const(2)]], TupleP [ConstP 1, TupleP[UnitP, Variable("s")]]) = SOME [("s", Const(2))]
val test1110 = match (Tuple [Const(1), Tuple [Unit, Const(2)]], TupleP [ConstP 2, TupleP[UnitP, Variable("s")]]) = NONE
val test1111 = match (Tuple [Const(1), Tuple [Unit, Const(2)]], TupleP [ConstP 1, TupleP[UnitP, Variable("s"), Wildcard]]) = NONE
val test11_ctor1 =  match(Constructor("A", Const 12), ConstructorP("B", ConstP 12)) = NONE
val test11_ctor2 =  match(Constructor("A", Const 12), ConstructorP("A", Variable "XYZ")) = SOME [("XYZ", Const 12)]

val test12 = first_match Unit [UnitP] = SOME []
val test1201 = first_match Unit [Variable ("s")] = SOME [("s", Unit)]
val test1202 = first_match (Tuple [Const(1), Tuple [Unit, Const(2)]]) [(TupleP [ConstP 1, TupleP[UnitP, Variable("s")]])] = SOME [("s", Const(2))]
val test1203 = first_match (Tuple [Const(1), Tuple [Unit, Const(2)]]) [(TupleP [ConstP 1, TupleP[UnitP, ConstP 3]])] = NONE

(* test 13 *)
val test1301_1 = get_type_list [] [ConstP 10, Variable "a"]
val test1302_1 = get_type_list [] [ConstP 10, Variable "a", ConstructorP("SOME",Variable "x")]
val test1303_1 = get_type_list [] [TupleP[Variable "a", ConstP 10, Wildcard], TupleP[Variable "b", Wildcard, ConstP 11], Wildcard]
val test1304_1 = get_type_list [("Red","color",UnitT),("Green","color",UnitT),("Blue","color",UnitT)] [ConstructorP("Red", UnitP), Wildcard]
val test1305_1 = get_type_list [("Sedan","auto", Datatype "color"),("Truck","auto",TupleT[IntT, Datatype "color"]),("SUV","auto",UnitT)] [ConstructorP("Sedan", Variable "a"), ConstructorP("Truck", TupleP[Variable "b", Wildcard]), Wildcard]
val test1306_1 = get_type_list [("Empty","list",UnitT),("List","list",TupleT[Anything, Datatype "list"])] [ConstructorP("Empty",UnitP),ConstructorP("List",TupleP[ConstP 10, ConstructorP("Empty",UnitP)]), Wildcard]
val test1307_1 = get_type_list [("Empty","list",UnitT),("List","list",TupleT[Anything, Datatype "list"])] [ConstructorP("Empty",UnitP),ConstructorP("List",TupleP[Variable "k", Wildcard])]
val test1308_1 = get_type_list [("Empty","list",UnitT),("List","list",TupleT[Anything, Datatype "list"])] [ConstructorP("Empty",UnitP),ConstructorP("List",TupleP[ConstructorP("Sedan", Variable "c"), Wildcard])]
val test1308_2 = get_type_list [("Red","color",UnitT),("Green","color",UnitT),("Blue","color",UnitT), ("Sedan","auto", Datatype "color"),("Truck","auto",TupleT[IntT, Datatype "color"]),("SUV","auto",UnitT), ("Empty","list",UnitT),("List","list",TupleT[Anything, Datatype "list"])] [ConstructorP("Empty",UnitP),ConstructorP("List",TupleP[ConstructorP("Sedan", Variable "c"), Wildcard])]
val test1309_1 = get_type_list [] [TupleP[Variable "x", Variable "y"], TupleP[Wildcard, Wildcard]]
val test13010_1 = get_type_list [] [TupleP[Wildcard, Wildcard], TupleP[Wildcard, TupleP[Wildcard,Wildcard]]]

val test1301 = typecheck_patterns([], [ConstP 10, Variable "a"]) = SOME IntT
val test1302 = typecheck_patterns([], [ConstP 10, Variable "a", ConstructorP("SOME",Variable "x")]) = NONE
val test1303 = typecheck_patterns([], [TupleP[Variable "a", ConstP 10, Wildcard], TupleP[Variable "b", Wildcard, ConstP 11], Wildcard]) = SOME (TupleT [Anything,IntT,IntT])
val test1304 = typecheck_patterns([("Red","color",UnitT),("Green","color",UnitT),("Blue","color",UnitT)], [ConstructorP("Red", UnitP), Wildcard]) = SOME (Datatype "color")
val test1305 = typecheck_patterns([("Sedan","auto", Datatype "color"),("Truck","auto",TupleT[IntT, Datatype "color"]),("SUV","auto",UnitT)], [ConstructorP("Sedan", Variable "a"), ConstructorP("Truck", TupleP[Variable "b", Wildcard]), Wildcard]) = SOME (Datatype "auto")
val test1306 = typecheck_patterns([("Empty","list",UnitT),("List","list",TupleT[Anything, Datatype "list"])], [ConstructorP("Empty",UnitP),ConstructorP("List",TupleP[ConstP 10, ConstructorP("Empty",UnitP)]), Wildcard]) = SOME (Datatype "list")
val test1307 = typecheck_patterns([("Empty","list",UnitT),("List","list",TupleT[Anything, Datatype "list"])], [ConstructorP("Empty",UnitP),ConstructorP("List",TupleP[Variable "k", Wildcard])]) = SOME (Datatype "list") 
val test1308 = typecheck_patterns([("Red","color",UnitT),("Green","color",UnitT),("Blue","color",UnitT), ("Sedan","auto", Datatype "color"),("Truck","auto",TupleT[IntT, Datatype "color"]),("SUV","auto",UnitT), ("Empty","list",UnitT),("List","list",TupleT[Anything, Datatype "list"])], [ConstructorP("Empty",UnitP),ConstructorP("List",TupleP[ConstructorP("Sedan", Variable "c"), Wildcard])]) = SOME (Datatype "list") 
val test1309 = typecheck_patterns([], [TupleP[Variable "x", Variable "y"], TupleP[Wildcard, Wildcard]]) = SOME (TupleT [Anything, Anything])
val test1310 = typecheck_patterns([], [TupleP[Wildcard, Wildcard], TupleP[Wildcard, TupleP[Wildcard,Wildcard]]]) = SOME (TupleT [Anything, TupleT[Anything, Anything]])
val test1311 = typecheck_patterns([("Sedan","auto", Datatype "color"),("Truck","auto",TupleT[IntT, Datatype "color"]),("SUV","auto",UnitT)], [ConstructorP("Sedan", Variable "a"), ConstructorP("Truck", TupleP[Variable "b", Wildcard]), ConstP 10]) = NONE