华中科技大学函数式编程
在’-‘提示符下直接输入SML语句,以分号结束;
表达式计算的结果缺省赋值给变量”it”;
文件的加载: use ;
如 use “d:\sml\test.sml”;
程序正确性检查:val =
如:val 42 = eval [2,4]
示例:
3+ 4;
3 + 2.0;
it + 6;
val it = “hello”;
it + “ world”;
it + 5;
val a = 5;
a = 6;
a + 8;
val twice = (fn x => 2 * x);
twice a;
let x = 1 in x end;
foo;
[1, “foo”];
2.完成函数mult的编写,实现求解整数列表中所有整数的乘积。
fun mult [ ] = 1 | mult (x ::L) = x*mult (L);
3.完成如下函数Mult: int list list -> int的编写,该函数调用mult 实现int list list中所有整数乘积的求解。
fun Mult [ ] = 1 | Mult (r :: R) = mult(r)*Mult(R);
4.利用mult’定义函数Mult’ : int list list * int -> int,使对任意整数列表的列表R和整数a,该函数用于计算a与列表R中所有整数的乘积。该函数框架如下所示,试完成代码的编写。
fun mult' ([ ], a) = a
| mult' (x :: L, a) = mult' (L, x * a);
fun Mult' ( [ ], a) = a
| Mult' (r::R, a) = Mult(R)*mult'(r,a);
fun double (0 : int) : int = 0
| double n = 2 + double (n - 1);
fun square(0:int):int =0
| square(x) = square(x-1)+double(x-1)+1;
fun divisibleByThree(x:int):bool =
if x=0 then true else
if x=1 then false else
if x=2 then false else
divisibleByThree(x-3)
;
fun oddP (0 : int) : bool = false
| oddP 1 = true
| oddP n = oddP (n - 2);
1.编写函数reverse和reverse’,要求:
函数类型均为:int list->int list,功能均为实现输出表参数的逆序输出;
函数reverse不能借助任何帮助函数;函数reverse’可以借助帮助函数,时间复杂度为O(n)。
(* 1
*function: reverse string like [a,b,c] to [c,b,a]
*require: true
*)
fun reverse [] = []
|reverse (a::L) = (reverse L) @ [a];
(* 2
*function: reverse string like [a,b,c] to [c,b,a] by using helper
*require: true
*)
fun reverse' (L : int list) : int list =
let
fun reversehelp' (L : int list, A : int list) : int list =
case L of
[ ] => A
| x::R => reversehelp' (R, x :: A)
in
reversehelp' (L, [ ])
end
(* 3
*function: cat string by seq
*require: true *
*)
fun interleave(A : int list,B : int list):int list =
case (A,B) of
([],_) => B
|(_,[])=> A
|(x::X,y::Y)=>x::y::interleave(X,Y)
3.编写函数listToTree: int list -> tree,将一个表转换成一棵平衡树。
提示:可调用split函数,split函数定义如下:
如果L非空,则存在L1, x, L2,满足:
split L = (L1, x, L2) 且
L = L1 @ x :: L2 且
length(L1)和length(L2)差值小于1。
(*4
*function: split strinf by middle
*require: true *
*)
fun split [] : (int list * int * int list) = raise Fail "cannot split empty list"
| split(l: int list) =
let
val mid = (length l) div 2
val L = (List.take (l,mid))
val x :: R = (List.drop (l,mid))
in
(L, x, R)
end
(*5
*function: seq list to balace tree
*require: true *
*)
fun listToTree ([]:int list):int tree = Empty
| listToTree (L)=
let
val (L, x, R) = split (L)
in
Node (listToTree(L), x , listToTree(R))
end
4.编写函数revT: tree -> tree,对树进行反转,使trav(revT t) = reverse(trav t)。(trav为树的中序遍历函数)。假设输入参数为一棵平衡二叉树,验证程序的正确性,并分析该函数的执行性能(work和span)。
(*val Empty = listToTree nil *)
(*5
*function: reverser tree seq-ly
*require: true *
*)
fun revT (Empty : int tree):int tree = Empty
| revT (Node(l,x,r)) = Node (revT (r), x , revT (l))
datatype 'a tree = Empty
| Node of 'a tree * 'a * 'a tree
(*6
*function: search tree by seq return bool
*require: true *
*)
fun binarySearch(Empty:int tree,i: int): bool = false
|binarySearch(Node(l,x,r), i) =
case Int.compare(x,i) of
GREATER => binarySearch(l,i)
| EQUAL => true
| LESS => binarySearch(r,i)
1.2
实验内容:
编写函数thenAddOne,要求:
函数类型为: ((int ->int) * int) -> int;
功能为将一个整数通过函数变换(如翻倍、求平方或求阶乘)后再加1。
(*平方*)
fun f1(x:int):int = x*x
(*平方+1*)
fun thenAddOne ((f1:int -> int), (x:int)) : int =
f1 x + 1
(**)
fun f2(x:int):bool =
if x=0
then false
else true
(*
mapList(f2,[1,2,0,3]);
*)
(*实现整数集的f数学变换*)
(*最终: ((‘a -> ‘b) * ‘a list) -> ‘b list
f x1::
(fx2::
(...
::mapList)))
*)
fun mapList (f: 'a -> 'b, [] : 'a list) : 'b list = []
| mapList (f, x::L) = (f x)::(mapList (f, L))
3.编写函数mapList’,要求:
① 函数类型为: (‘a -> ‘b) -> (‘a list -> ‘b list);
② 功能为实现整数集的数学变换(如翻倍、求平方或求阶乘)。
③ 比较函数mapList’和mapList,分析、体会它们有什么不同。
(*
(‘a -> ‘b) -> (‘a list -> ‘b list);
类上,不过类型变化
*)
fun mapList' (f : 'a -> 'b) ([] : 'a list) : 'b list = []
|mapList'(f)(x::L)=(f x)::(mapList' f L);
4.编写函数findOdd,要求:
① 函数类型为: int list -> int option;
② 功能为:如果x为L中的第一个奇数,则返回SOME x;否则返回NONE
(**)
fun findOdd([] : int list): int option = NONE
| findOdd(x::L) = if (x mod 2)=1 then SOME x else findOdd L
5.编写函数subsetSumOption: int list * int -> int list option,要求:
对函数subsetSumOption(L, s):如果L中存在子集L’,满足其中所有元素之和为s,则结果为SOME L’;否则结果为NONE。
(*参考找零问题*
*)
fun subsetSumOption (l : int list, 0 : int) : int list option = SOME []
| subsetSumOption ([], n) = NONE
| subsetSumOption (x::L, sum) =
if subsetSumOption(L, sum-x) =NONE
then subsetSumOption(L, sum) (*不符合,去掉x*)
else
SOME (x::(valOf(subsetSumOption(L, sum-x))))
(*符合,SOME加上x*)
(*
p传入函数
fun foldr F z [ ] = z
| foldr F z (x::L) = F(x, foldr F z L)=F(x, result)
递归,结果或orelse
p a orelse
p b orelse
foldr p true L
*)
fun exists (p : 'a -> bool) (l : 'a list) : bool =
foldr (fn (a,b) => p a orelse b) false l
(*
类上,结果与,andalso
若foldr (Func) result object
*)
fun forall (p : 'a -> bool) (l : 'a list) : bool =
foldr (fn (a,b) => p a andalso b) true l
datatype 'a tree = Empty
| Node of 'a tree * 'a * 'a tree
(*
从根节点开始,将x替换成y
*)
fun treeFilter (p : 'a -> bool ) (Empty) : 'a option tree = Empty
| treeFilter (p) (Node (l, x, r)) =
let
val y = if p x then SOME x else NONE
in
Node (treeFilter p l, y, treeFilter p r)
end