第八章 构造我们自己的类型及类型类.pdfVIP

  • 5
  • 0
  • 约2.14万字
  • 约 19页
  • 2017-06-07 发布于湖北
  • 举报

第八章 构造我们自己的类型及类型类.pdf

第⼋章 构造我们⾃⼰的类型和类型类 数据类型⼊门 Record Syntax 类型参数 派⽣实例 类型别名 数据类型⼊门 在前⾯的章节中,我们谈了⼀些Haskell 内置的类型和类型类。 在本章,我们将学习 构造类型和类型类的⽅法。 我们以已经见识了许多数据类型,如Bool、Int、Char、Maybe等等,不过该怎样 构造⾃⼰的数据类型呢?好问题,使⽤data关键字是⼀种⽅法。我们看看Bool在标准 库中的定义: data Bool = False | True data表⽰我们要定义⼀个新的数据类型。=的左端标明类型的名称即Bool,=的右端 就是值构造⼦ (Value Constructor ),它们明确了该类型可能的值。|读作“或” ,所以 可以这样阅读该声明:Bool类型的值可以是True或False 。类型名和值构造⼦的⾸字 母必⼤写。 相似,我们可以假想Int类型的声明: data Int = -2147483648 | -2147483647 | ... | -1 | | 1 | 2 | ... | ⾸位两个值构造⼦分别表⽰了Int类型可能的最⼩值和最⼤值,这些省略号表⽰我们省 去了中间⼤段的数字。当然,真实的声明不是这个样⼦的,这样写只是为了便于理 解。 我们想想Haskell 中图形的表⽰⽅法。表⽰圆可以⽤⼀个元组,如 (43.1,55. ,1 .4),前两项表⽰圆⼼的位置,末项表⽰半径。听着不错,不过三 维向量或其它什么东西也可能是这种形式 !更好的⽅法就是⾃⼰构造⼀个表⽰图形的 类型。假定图形可以是圆 (Circle )或长⽅形 (Rectangle ): data Shape = Circle Float Float Float | Rectangle Float Float Floa 这是啥,想想?Circle的值构造⼦有三个项,都是Float 。可见我们在定义值构造⼦ 时,可以在后⾯跟⼏个类型表⽰它包含值的类型。在这⾥,前两项表⽰圆⼼的坐标, 尾项表⽰半径。Rectangle的值构造⼦取四个Float项,前两项表⽰其左上⾓的坐 标,后两项表⽰右下⾓的坐标。 谈到“项”(field) ,其实应为“参数”(para eters) 。值构造⼦的本质是个函数,可以返回⼀ 个类型的值。我们看下这两个值构造⼦的类型声明: ghci :t Circle Circle :: Float - Float - Float - Shape ghci :t Rectangle Rectangle :: Float - Float - Float - Float - Shape Cool ,这么说值构造⼦就跟普通函数并⽆⼆致咯,谁想得到?我们写个函数计算图形 ⾯积: surface :: Shape - Float surface (Circle _ _ r) = pi * r ^ 2 surface (Rectangle x1 y1 x2 y2) = (abs $ x2 - x1) * (abs $ y2 - y1 值得⼀提的是,它的类型声明表⽰了该函数取⼀个Shape值并返回⼀个Float值。写 Circle - Float是不可以的,因为Circle并⾮类型,真正的类型应该是Shape 。这 与不能写True-False的道理是⼀样的。再就是,我们使⽤的模式匹配针对的都是 值构造⼦。之前我们匹配过[]、False或5,它们都是不包含参数的值构造⼦。 我们只关⼼圆的半径,因此不需理会表⽰坐标的前两项: ghci surface $ Circle 1 2 1 314 .15927 ghci surface $ Rectangle 1 1 1 . Yay ,it works !不过我们若尝试输出Circle 1 2 到控制台,就会得到⼀个错误。 这是因为Haskell还不知道该类型的字符串表⽰⽅法。想想,当我们往控制台输出值的 时候,Haskell会先调⽤show函数得到这个值的字符串表⽰才会输出。因此要让我们的 Shape类型成为Show类型类的成员。可以这样修改: data Shape = Circle Float Float Float | Rectangle Float Float Floa 先不去深究deriving (派⽣),可以先这样理解:若在data声明的后⾯加上d

文档评论(0)

1亿VIP精品文档

相关文档