《Real World Haskell》笔记(2):类型与函数

Haskell类型系统

静态、强类型检查使得 Haskell 更安全,而类型推导则让它更精炼、简洁。正是自动推导帮助 Haskell 程序既可以获得静态类型带来的所有好处,而又不必像传统的静态类型语言那样,忙于添加各种各样的类型签名(如 C 语言的函数原型声明)

强类型系统使Haskell拒绝执行任何无意义的表达式,并且不会自动地将值从一个类型转换到另一个类型;静态类型系统则使Haskell编译器可以在编译期(而不是执行期)知道每个值和表达式的类型;Haskell类型可以通过自动推导得出。

类型签名

类型签名(v.) 即为表达式显式的指明类型
输入var::T,向解释器或编译器表明var的类型是T。显示签名必须正确,否则 Haskell 编译器就会产生错误;若未显式签名,则类型由自动推导决定。

一些基本类型

Char单个Unicode字符
Bool表示一个布尔逻辑值,该类型只有两个值: True 和 False
Int带符号的定长整数
Integer带符号的非定长整数
Double浮点数

复合数据类型

列表 [a]
性质:类型多态(polymorphic)列表元素的值可以是任意类型(但所有元素必须同种类型)
方法:

  • head 返回列表的第一个元素
  • tail 返回列表里除了第一个元素之外的其他元素
  • init 返回除了最后一个元素的其他部分
  • last 返回最后一个元素
  • take n list 从list中取前n个元素组成list,n>=0,如果n=0,得到一个空list
  • drop n list 删除一个 List 中的前n个元素
  • length 返回长度
  • null 检测是否为空
  • reverse 反转序列
  • maximum/minimum 得到最大/小元素(list中的元素必然可以比较)
  • sum 求和
  • elem x list 判断x是否存在于list中
  • notElem
  • concat 取一个包含列表的列表 去掉一级的嵌套 连接列表在成为一个单一的列表
  • and、or 针对包含Bool值的列表 相当于用&&和||遍历这个列表并两两求值
  • splitAt 返回由一个列表产生的二元组 两部分是由原来的列表根据给定的索引分割而成
  • takeWhile、dropWhile 从开头遍历一个列表 抽取或抛弃使谓词返回True的元素(实际上两个函数都是走到第一个使谓词返回False的元素处就停止操作,即使这个元素后面还有使谓词返回True的元素,两个函数也不再take或drop)
  • break、span 提取列表中使谓词失败、成功(即第一次使谓词成功、失败的所有前驱)的元素组成二元组的首项
  • filter 返回列表中使谓词成功的每一个元素
  • Data.List.isPrefixOf xs xs_ 判断左边列表是否出现在右边的列表的开始处
  • Data.List.isInfixOf xs xs_ 判断左边列表是否是右边的列表的一个子列表
  • Data.List.isSuffixOf xs xs_
  • zip xs xs_ 把两个列表压缩成一个单一的由二元组组成的列表,如果两个list中的元素个数不一致,以较短的那个为界
  • zipWith func xs xs_ 它带两个列表作为参数并为从每个列表中抽取一个元素而组成的二元组提供一个函数,最后生成与较短的那个列表等长的新列表

元组
性质:元组的类型由它所包含元素的数量、位置和类型决定(如果两个元组里都包含着同样类型的元素,而这些元素的摆放位置不同,那么它们的类型就不相等)
方法:

  • fst 返回首项
  • snd 返回次项
调用函数

compare (sqrt 3) (sqrt 6)

  • 函数应用的优先级比操作符要高
  • 调用一个函数,先写出它的名字,后接函数的参数
  • 函数的参数不需要用括号来包围,参数和参数之间不用逗号而用空格来隔开
  • 为了可读性考虑,可以添加一些额外的括号,示例调用,若不加括号,Haskell认为我们将四个参数传给了只需要两个参数的 compare 函数
传表达式给函数

Haskell 的函数应用是左关联的。比如说,表达式 a b c d 等同于 (((a b) c) d),要将一个表达式用作另一个表达式的参数,那么就必须显式地使用括号来包围它,若移走括号,那么编译器就会认为我们试图将多个参数传给函数。

函数类型

lines::String->[String]
String -> [String] 的实际意思是指 lines 函数定义了一个从 String 到 [String] 的函数映射。
理解为,lines 函数接受一个字符串作为输入,并将这个字符串按行转义符号(换行符)分割成多个字符串后返回字符串列表。所以,函数的类型签名可以提示函数自身的功能。

多参数函数的类型

take::Int->[a]->[a]
类型签名中的 -> 符号是右关联的:Haskell 从右到左地串联起这些箭头,使用括号可以清晰地标示即take::Int->([a]->[a])

条件求值:if表达式
--file myDrop.hs
myDrop n xs = if n<=0 || null xs
  then xs
  else myDrop (n-1) (tail xs)
  • 跟在 if 之后的是一个 Bool 类型的表达式,它是 if 的条件部分
  • 跟在 then 关键字之后的是另一个表达式,这个表达式在条件部分的值为 True 时被执行
  • 跟在 else 关键字之后的又是另一个表达式,这个表达式在条件部分的值为 False 时被执行
  • 跟在 then 和 else 之后的表达式称为“分支”。不同分支之间的类型必须相同
多态

当需要编写带有多态类型的代码时,需要使用类型变量。这些类型变量以小写字母开头,作为一个占位符,最终被一个具体的类型替换。
如,[a] 用一个方括号包围一个类型变量 a ,表示一个“类型为 a 的列表”,当需要一个带有具体类型的列表时,就需要用一个具体的类型去替换类型变量, [Int] 表示一个包含 Int 类型值的列表,它用 Int 类型替换了类型变量 a 。

练习

写一个函数 lastButOne, 返回列表倒数第二个元素

--file lastButOne.hs
lastButOne xs=if length xs==2
  then head xs
  else lastButOne (tail xs)

该函数输入列表长度须大于等于2,否则引发异常Exception: Prelude.tail: empty list,即异常原因是tail函数应用于空列表。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,245评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,749评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,960评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,575评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,668评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,670评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,664评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,422评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,864评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,178评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,340评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,015评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,646评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,265评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,494评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,261评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,206评论 2 352

推荐阅读更多精彩内容