学习了scala 与swift 之后,觉得对函数编程理解的不够,
本来是想在学学Haskell的,后来想想一直想学F#,还是先学F#吧,只作为我的一个笔记
F# 在复合类型上,比scala与C# 多了记录和联合
type FullName = {First: string; Last: string;} type Vehicle = | Car | Truck | Bus [<EntryPoint>] let main argv = let a = { First = "Brown" ; Last = "Mike" } let b = Car 0 // 返回整数退出代码
都使用type 关键字来定义type FullName = {First: string; Last: string;} 这样就定义了记录
let b = Car 这样就定义了联合。
当定义变量的时候,编译器隐式的将a 和b 分别的推断为FullName 与Vehicle,也可以像下面一样显示的指明:
let a : FullName = { First = "Brown" ; Last = "Mike" } let b : Vehicle = Car
在F# 中联合类型非常灵活,它的各个分量可以取不同的类型:
type School = { Name : string; Department: string; } type Address = | Common of string | Street of string * string * int | School of School [<EntryPoint>] let main argv = let a1 = Street("朝阳区","建外大街",31) let a2 = School({Name = "北京工业大学"; Department = "数学系"}) 0 // 返回整数退出代码
联合甚至还可以进行递归定义:
type Route = | Direct of (string * string) | Transfer of (string * Route) [<EntryPoint>] let main argv = let r1 = Direct("北京","厦门") let r2 = Transfer("上海",r1) 0
可变类型
let 代表的是不可变,虽然函数式推荐我们使用不可变,但有时候还是需要使用可变类型:
let mutable x = 5 x <- 6
使用关键字 mutable 代表可变变量,使用<-进行赋值。
默认情况下,记录中的字段也是不可变的:
type Score = { mutable Math: int; Phys: int; Chem: int } [<EntryPoint>] let main argv = let s = { Math = 90; Phys = 95; Chem = 80} s.Math <- 100 //编译成功 s.Phys <- 101 //编译出错 0
引用类型
另一种改变值得方法是使用引用类型,方法是在数值前面加上关键字ref,列如:
let y = ref 2.25 //使用引用类型 y := !y + 0.2 //访问时加上!符号,赋值运算为 :=
可变值与引用值最大的区别就是,可变值存储的是值类型,引用值存储的是指针。
[<EntryPoint>] let main argv = let mutable x1 = "old value" let mutable x2 = x1 x1 <- "new value" printfn "%s" x2 let y1 = ref "old value" let y2 = y1 y1 := "new value" printfn "%s" !y2 0
x1 存储的是值类型, y1 存储的是引用类型
可选类型
let mutable x = Some(50) x <- Some(40) x <- None printfn "%i" (if x.IsNone then 0 else x.Value)
以上就定义了可选类型,可选类型可以取整数,也可以取空值,
实际上int option类型相当于以下的联合类型定义:
type IntOption = | Some of int | None