F# 的类型系统提供了多种方法来让我们定义自己的类型。而所有的类型最后还是归于两种,

一种叫 Tuple 或者是 Records,他们跟 C 的 Struct 与 C# 的 Class 很相似。

另一种则是 sum 类型,有时他们也指 Union 类型。

下面我们先讲 Record

Tuple 是一种快速且简易的方式帮助我们将各个值封装到一个组里。而且也提供了方法让我们将 Tuple

里的值单独取出。看一个简单的例子;

#light

let pair = true, false

let b1, _ = pair

let _, b2 = pair

在这里,我们使用下划线 _ 来表示忽略某个值,比如 b1, _ = pair 则表示我们只需要第一个值,此时则忽略了

第二个值,后面的表达式也是同一个意思。

而我们也可以使用关键字 type 来定义另一种类型。比如为一个 tuple 取别名,下例:

#light

type Name = string

type Fullname = string * string

let fullNameToString (x : Fullname) =
    let first, second = x in
    first + " " + second

上例表示了传递一个 Fullname 类型,并将其转化为 string 的方法。而 Fullname 实际上就是一个 Tuple

Record 类型有点类似于 Tuple 可用于将多个类型的值绑定到一个别名或一个组,而他们的区别则主要

在于,Record 可以为绑定的值命名。下面看一个例子

#light

type Organization1 = { boss : string; lackeys : string list }

let rainbow =

{ boss = "Jeffrey";

lackeys = ["Zippy"; "George"; "Bungle"] }

type Organization2 = { chief : string ; underlings : string list }

type Organization3 = { chies : string ; indians : string list }

let thePlayers =

{ new Organization2

with chief = "Peter Quince"

and underlings = [ "Francis Flute"; "Robin Starveling";

"Tom Snout"; "Snug"; "Nick Bottom"] }

let wayneManor =

{ new Organization3
         with chief = "Batman"
         and indians = ["Robin"; "Alfred"] }

F# 并没有强制 Record 里的命名必须是唯一的,所以当编译器无法推断出类型的时候,你最好还是加上类型声明。

而当如果你定义的类型里面需要使用到你下面即将定义的另外一个类型,

你可以使用 and 关键字来告诉编译器。看例子

#light

type recipe =
    { recipeName : string ;
      ingredients : ingreddient list;
      instructions : string }
and ingredient =
    { ingredientName : string ;
      quantity : int }

let greenBeansPineNuts =
    { recipeName = "Green Beans & Pine Nuts" ;

ingredients =
          [ { ingredientName = "Green beans"; quantity = 250 };
            { ingredientName = "Pine nuts"; quantity = 250 }] //后面还有很多,略

instructions = "Parboil the green beans for about minutes ........."}

let name = greenBeansPineNuts.recipeName

let toBuy =
    List.fold //原书为 fold_left 在 F# 2.0 中已取消
        (fun acc x ->
            acc +
            (Printf.sprintf "\t%s - %i\r\n" x.ingredientName x.quantity) )
        "" greenBeansPineNuts.ingredients

let instructions = greenBeansPineNuts.instructions

printf "%s\r\n%s\r\n\r\n\t%s" name toBue instructions

这里应该都没啥问题,唯一需要解释的可能是 fold函数。我们来看看他的定义

val it : (('a -> 'b -> 'a) -> 'a -> 'b list -> 'a) = <fun:clo@42>

参数的定义我就不解释了,免得越说越乱。他其实就是使用传递的第一个参数: 一个匿名函数

对第三个 参数 : 一个 b 类型的列表进行遍历,进行处理,然后第二个就是一个状态值,他用来保存

每次执行 匿名函数后的结果。

所以像上面的 toBuy 函数执行的结果其实就是将 ingredients 的每个元素按一定的规则转化为字符串,

并连接起来。

下面我们来看一个 Record 的模式匹配。

#light

type couple = { him : string; her : string }

let couples =

[ { him = "Brad"; her = "Angelina" };
      { him = "Becks"; her = "Posh" };
      { him = "Chris"; her = "Gwyneth" };
      { him = "Michael" her = "Catherine" } ]

let rec findDivid l =
    match l with
    | { him = x ; her = "Posh" } :: tail -> x
    | _ :: tail -> findDavid tail
    | [] -> failwith "couldn't find David"

printf findDavid couples

上面的就比较简单易懂了,定义了一个 夫妻 (couple) 类型,里面有 丈夫 (him) 跟 妻子 (her) 两个字段,

然后定义了一个 夫妇 (couple)的列表, 接着的一个函数则在这个列表中查找第一个 妻子 (her) 名为

Posh 的夫妇,找到后把丈夫的名字赋予标识符 x ,然后返回 x, 如果没找到则抛出找不到的异常。

转载于:https://www.cnblogs.com/SinSay/archive/2010/09/27/1836437.html

Chapter3 - Defining Types - Record相关推荐

  1. 政府跟踪我们电话的3种方式

    You may have heard of people being tracked by simply owning a phone - it's entirely true. You could ...

  2. sql组合键设置外键_学习SQL:外键

    sql组合键设置外键 In the previous article, we talked about the primary key (PK). In this one, we'll check w ...

  3. INTRODUCING F#

    第一篇,从零开始编写我们的第一个F#程序. 什么是F#,我为何要学它? F#是一种.NET平台上的函数式编程语言.就像C#和VB.NET,F#可以利用.NET的核心类库,如WPF,WCF,VSTO等等 ...

  4. sql 复合主键 联合主键_学习SQL:主键

    sql 复合主键 联合主键 If you've already worked with databases, then you could hardly miss the term – Primary ...

  5. Linker Linking (a detail introduction)

    http://eulertao.ycool.com/post.1822428.html 超级长的文章,连载20天,作者牛啊- http://www.airs.com/blog/archives/cat ...

  6. 为什么要在JavaScript中使用静态类型? (使用Flow进行静态打字的4部分入门)

    by Preethi Kasireddy 通过Preethi Kasireddy 为什么要在JavaScript中使用静态类型? (使用Flow进行静态打字的4部分入门) (Why use stati ...

  7. java读avro的流_0016-Avro序列化反序列化和Spark读取Avro数据

    1.简介 本篇文章主要讲如何使用java生成Avro格式数据以及如何通过spark将Avro数据文件转换成DataSet和DataFrame进行操作. 1.1Apache Arvo是什么? Apach ...

  8. GCC 生成的符号表调试信息剖析

    GCC把C语言源文件('.c')编译成汇编语言文件('.s'),汇编器把汇编语言文件翻译成目标文件('.o'),最后由链接器链接所有的目标文件和有关的库生成可执行文件('a.out'). 如打开'-g ...

  9. 为什么要在JavaScript中使用静态类型? 我们是否应该使用它们?

    by Preethi Kasireddy 通过Preethi Kasireddy 为什么要在JavaScript中使用静态类型? 我们是否应该使用它们? (Why use static types i ...

最新文章

  1. 常用免费精品Web应用列表(转)
  2. java中集合的结构(list和map)
  3. [转载]Ubuntu安装配置Mysql
  4. 免责协议怎么写_离婚后房产过户协议怎么写?需要公证吗?
  5. [转]DotNet C#开源资源汇总
  6. 哪个相机可以拍gif动图_入门级微单相机哪家强?索尼微单A6400评测来了!
  7. SpringBoot史前简述
  8. nohup命令简单的使用
  9. Atitit. Toast alert loading js控件   atiToast v2新特性
  10. 史上超强图像处理开源工具包--ImageMagick
  11. 数字经济是党和国家定下的重要发展战略
  12. 软件工程基础知识--系统设计
  13. 【英语竞赛】听力速记
  14. 2020第十一届蓝桥杯-决赛-Java大学-C组
  15. excel锁定单元格不能修改_【软件应用】工程中经常运用的Excel技巧(附教程下载)...
  16. AD域控管理之授权普通用户或组管理计算机加入域和退出域的权限
  17. 博主文章导航(分门别类,实时更新,永久置顶)
  18. ios应用数据存储方式(偏好设置)-转
  19. 最全的Windows Azure学习教程汇总
  20. Python环境配置和安装包总结

热门文章

  1. RE2,C++正则表达式库实战
  2. 三星s9 android 版本,三星S9系列/Note9更新One UI:正式推送Android9.0
  3. 在word中怎么设置从中间某一页开始插入页码
  4. 利用circom和snarkjs实现zkSNARK零知识证明的智能合约应用
  5. Revit软件是用来做什么的?可以快速出图的revit插件
  6. 盒马 iOS Live Activity “灵动岛”配送场景实践
  7. windows防火墙设置_TinyWall下载 _TinyWall(网络防火墙)官方版下载安装3.0.9
  8. 数据库,我们该如何选型?
  9. 《Regularized Evolution for Image Classifier Architecture Search》论文阅读笔记
  10. HTML班级网页设计 基于HTML+CSS+JS制作我们的班级网页(web前端学生网页设计作品)...