函数式编程原理
一、ML标准类型
- 基础类型(basic types):unit,int,real,bool,string
其中的unit类似于C语言中的void
-
表(list):int list,(int ->int)list
-
元组(tuples):int *int,int * int * real
-
函数(functions):int->int,real->int * int
所有对象都要有类型,不一定显示说明,但必须能够静态推导(在编译时该类型能被编译器根据上下文推算出来)
1.ML基础类型
-
单元unit:只包含一个元素,用空的括号表示,()
-
整型int: 负号用~表示
-
浮点型real
-
布尔型bool:true,false
-
字符串型string:双引号间的字符序列
2.表lists
- 包含相同类型元素的优先序列
- 表中元素用逗号分隔,这个那个表用[ ]括起来
- 元素可以重复出现,其顺序有意义
- 表的类型取决于表中元素类型(可以为任意类型,但需具有相同的类型)
- 表可以嵌套
- 表的基本函数
:: 追加元素
@ 连接表
null 空表测试
hd 返回表头元素
tl 返回非空表的表尾
length 返回表长
3.元组tuples
- 包含任意类型数据元素的定长序列
- 类型表达式:每个元素的类型用*间隔并排列在一起
- 圆括号中用逗号分隔数据元素,允许嵌套
4.记录record
- 类似C语言中的结构类型,可以包含不同类型的元素
- 每个元素都有一个名字
- 记录的值和类型的写法都用{ }括起来
5.函数function
- 以一定的规则将定义域上的值映射到值域上去
- 类型由它的定义域类型和值域类型共同描述
- ->表示定义域到值域的映射
二、ML标准函数
-
标准布尔函数:not,andalso,orelse
-
标准算数运算函数:~,+,-,*,div,/
运算符重载(operator):把同一运算符作用在不同类型上
重载运算符的两边必须为同一类型
整数到实数的转换:real
实数到整数的转换:floor(下取整),ceil(上取整),round(四舍五入),trunc(忽略小数)
-
标准字符串函数:
把两个字符串合并成一个:^
返回字符串的长度:size
1.值Values
- 每个类型都有一个值的集合
- 一个类型的表达式求值结果为该类型的一个值(或出错)
- 严格类型检查
2.声明Declarations
-
赋予某个对象一个名字,包括值、类型、签名、结构和函子
-
函数的声明:
fun <函数名> (<形式参数>) : <结果类型> = <函数体>
-
值的声明:
val pi=3.1415
-
采用静态绑定方式—重新声明不会破环系统、库或程序
-
任意一个类型的表达式都可以进行求值操作
-
任意一个类型表达式求值的结果为该类型的一个值
-
ML提供重新声明功能
-
声明将产生名字和值的绑定(binding)
-
绑定具有静态作用域
2.1声明的使用
check : int * int -> bool
2.2声明的作用域
函数定义的两种方法
-
fun circ(r:real):real = 2.0*pi*r;
-
fun cirl(r:real):real=
let
val pi2:real=2.0*pi
in
pi2*r
end
let D in E end 是局部声明
3.ML中的“=”
- “=”用于类型的等式判断,称为等式类型
- 等式类型包括整数、布尔值结合元组、表等构造子生成的类型
4.模式匹配
- 模式与值进行匹配
- 匹配成功,将产生一个绑定(binding)
- 匹配不成功,声明就会失败
5.求值符号的使用
- e=> e’ 一次推导
- e=>* e’ 有限次推到
- e=>+e’ 至少一次推导
三、模式匹配举例
fun eval ([]:int list):int=0
| eval (d::L)=d+10*(eval L);
fun decimal (n:int):int list=
if n<10 then [n]
else (n mod 10)::decimal(n div 10);
fun exp(n:int):int=
if n=0 then 1 else 2*exp(n-1);
fun square (x:int):int=x*x;
fun fastexp(n:int):int=
if n=0 then 1 else
if n mod 2 = 0 then square(fastexp(n div 2))
else 2*fastexp(n-1)
fun pow(n:int):int=
case n of
0=>1
| 1=>2
| _=>let
val k=pow(n div 2)
in
if nmod 2 = 0 then k*k else 2*k*k
end
fun badpow(n:int):int=
case n of
0=>1
| 1=>2
| _=>let
val k2=badpow(n div 2)*badpow(n div 2)
in
if n mod 2 = 0 then k2 else 2*k2;
end
fun fib 0=1
| fib 1=1
| fib n=fib(n-1)+fib(n-2)