programming-languages学习笔记–第2部分
Table of Contents
1 自定义类型
- 基本类型 (int bool unit char)
- 复合类型 (tuples, lists, options)
构造复合类型:
- each of: 组合所有 例如:tuples, (int * bool) 包含一个int和一个bool, 与java中带的字段类相似
- one of: 选择一个 例如:option, int option可以包含一个int或者空,java中可以通过子类化实现。
- self reference: 自引用类型,用于构造递归数据类型,例如列表和树
list使用了全部3种构造
2 Records
属于"each-of"类型:
- record的值用字段来保存
- record的类型也用字段保存
- 字段的顺序无关紧要
与tuple相比更容易记忆(有字段名),
注意代码中-开始的行是repl的输入,下面是输出。
- val x = {bar = (1+2, true andalso true), foo = 3+4, baz = (false,9)}; val x = {bar=(3,true),baz=(false,9),foo=7} : {bar:int * bool, baz:bool * int, foo:int} - #bar x; val it = (3,true) : int * bool - #foo x; val it = 7 : int
ML中不需要定义record类型,直接写record表达式,类型检查器会给出正确的类型。
3 tuples as syntactic sugar
records和tuples很相似。都是"each-of"构造。唯一的不同是records通过名称访问,tuples通过位置访问。 java的方法调用组合了这两种方式:方法内使用变量名访问不同的参数,但调用者通过位置传递参数。
可以通过构造records来定义tuples:
- - val a_pair = (3+1, 4+2); val a_pair = (4,6) : int * int - - val a_record = {second=4+2, first=3+1}; val a_record = {first=4,second=6} : {first:int, second:int} - - val another_pair = {2=5, 1=6}; val another_pair = (6,5) : int * int - - #1 a_pair + #2 another_pair; val it = 9 : int - - val x = {3="hi", 1=true}; val x = {1=true,3="hi"} : {1:bool, 3:string} - - val y = {3="hi", 1=true, 2=3+2}; val y = (true,5,"hi") : bool * int * string
实际上,tuple就是record, tuple是record的语法糖
方便设计实现(语言核心足够简单),方便理解
4 datatype bindings
datatypee mytype = TwoInts of int * int | Str of string | Pizza
每个mytype的值都从一个构造器产生 每个值包括:构造的tag, 对应的数据
上面的示例创建一个新类型 mytype 和3个构造器 TwoInts, Str, Pizza
要访问datatype的值,需要:
- 检查是哪个构造器构造的
- 提取数据
例如: null 和 isSome检查; ht,tl 和 valOf 提取数据
- - datatype exp = Constant of int | Negate of exp | Add of exp * exp | Multiply of exp * exp ; datatype exp = Add of exp * exp | Constant of int | Multiply of exp * exp | Negate of exp - - val r = Add (Constant (10 + 9), Negate (Constant 4)); val r = Add (Constant 19,Negate (Constant 4)) : exp - - fun eval e = case e of Constant i => i | Negate e2 => ~ (eval e2) | Add(e1, e2) => (eval e1) + (eval e2) | Multiply(e1,e2) => (eval e1) * (eval e2) ; = val eval = fn : exp -> int - - eval r; val it = 15 : int
5 case 表达式
ML使用case表达式和模式匹配访问"one-of"值
- - datatype mytype = TwoInts of int * int | Str of string | Pizza ; = datatype mytype = Pizza | Str of string | TwoInts of int * int - fun f (x : mytype) = case x of Pizza => 3 | Str s => 8 | TwoInts(i1, i2) => i1 + i2 ; = val f = fn : mytype -> int - - f Pizza; val it = 3 : int - - f (TwoInts (7, 9)); val it = 16 : int
6 类型别名
type aname = t
两个名字可以互换使用
- datatype suit = Club | Diamond | Heart | Spade ; datatype suit = Club | Diamond | Heart | Spade - datatype rank = Jack | Queen | King | Ace | Num of int; datatype rank = Ace | Jack | King | Num of int | Queen - type card = suit * rank; type card = suit * rank - type name_record = { student_num : int option, first : string, middle : string option, last : string }; type name_record = {first:string, last:string, middle:string option, student_num:int option} - fun is_Queen_of_Spades (c : card) = #1 c = Spade andalso #2 c = Queen; val is_Queen_of_Spades = fn : card -> bool - val c1 : card = (Diamond, Ace); val c1 = (Diamond,Ace) : card - val c2 : suit * rank = (Heart, Ace); val c2 = (Heart,Ace) : suit * rank - val c3 = (Spade, Ace); val c3 = (Spade,Ace) : suit * rank - is_Queen_of_Spades c1; val it = false : bool - is_Queen_of_Spades c2; val it = false : bool - is_Queen_of_Spades c3; val it = false : bool
7 Lists和Options也是datatype
模式匹配的优点: 不会有例外情况。