Haskell常用数据形式与函数

Function

defineName param = f(param)
模式匹配(pattern matching)为不同的模式分别定义函数体,注意匹配所有情况的模式应写到最后,类似switch/case,但匹配的是结构,关系具体内容的是哨位(guard)。

某种意义上函数名后的参数判断本身就是“模式匹配”,注意类型注解和模式匹配中的括号意味着元组和表达式
两种情况,由于元组内部被逗号分隔,容易分辨

defineName1 :: type1->type2
defineName1 a = f()
defineName1 x = f(x)
guard通过检查参数的性质是否为真(布尔判断),契合模式匹配的多条件分支。模式与guard相似的地方是对内容的判断(模式的结构包含内容),稍微不同的是guard能对参数组合后的内容进行判断。
元组的模式匹配指将每个成员分别写出来
列表中[]匹配空列表,可以用: 与 []匹配非空列表,x:xs将列表的头部绑定为x,余下部分为xs。
x:y:[]相当于[x,y]匹配长度固定的列表。
不能在列表的模式匹配中使用++,
as模式(as-pattern),允许按模式将一个值分隔成多个项,同时仍保留对其整体的引用。
如all@(x:y)

Prelude> firstletter all@(x:y) = "The first letter of "++all++" is "++[x]
Prelude> firstletter ['a','c','d']
"The first letter of acd is a"

case

模式匹配是case表达式的语法糖,函数参数的模式匹配只能在定义函数时使用,而case表达式可用在任何地方,始终没有匹配的模式,将会产生运行时错误,注意用空格缩进。注意typeclass与pattern的差别。

case expression of pattern -> result
                   pattern -> result
                   pattern -> result
                  ...

where

函数where中定义的名字只对本函数可见,不必担心它会污染其它函数的命名空间。如果要对不同的函数重复使用到同一名字,应把它置于全局定义中。可以在where绑定中使用模式匹配和定义函数,但where中定义的名字不能在函数的其它模式访问?,最后一个模式可见,guard也可见。

let

let表达式的格式为let <bindings> in <expressions>。绑定的名字仅对in部分可见,本身是表达式一定有返回值。let把绑定语句放前面,后跟表达式,与where相反。(指where与其函数的整体)。直接在GHCi中定义let可省略in,这样名字的定义在整个会话中可见,由于没有in也不会出现返回值。

Prelude> let havefun x y = [x..y]
Prelude> havefun 1 5
[1,2,3,4,5]
Prelude> let hadfun x y = [x..y] in hadfun 3 7
[3,4,5,6,7]
Prelude> hadfun

<interactive>:61:1: error:
    • Variable not in scope: hadfun
    • Perhaps you meant ‘havefun’ (line 58)

list (列表是单类型的)

  1. 字符串是一组字符组成的列表,"hello"是['h','e','l','l','o']的语法糖
  2. [1,2,3]是1:2:3:[]的语法糖
  3. 嵌套列表的元素同样不能混合放置类型
    a. 拼接字符串 list ++ list(会遍历第一个列表)
    b. 添加字符串 element : list
    c. 访问元素 list(string) !! index
    d. 比较元素 <、 >、 >=、<=、==、 /=
    e. 逻辑符号 &&、||、not
    f. 列表头尾操作 head、tail、last、init (不要用到空列表[]上)
    g. 列表属性 length返回长度,null检查是否为空,reverse反转列表,maximum取最大元素,minimum取最小元素,sum与product返回和与积
    h. 截取操作,take number list 取出列表的前number个,返回列表;drop number list 返回删除前number个的列表。element elem list判断元素是否包含于列表
    i. 区间,[a,n*a..b], [a..b],[a,n*a..]。cycle函数接受一个列表作为参数并返回一个无限列表;repeat函数接受一个值作为参数,返回一个仅包含该值的无限列表。replicate接受列表长度和复制的元素,takeWhile取一个谓词和列表作为参数,在元素符合谓词时返回元素,一旦不符合条件就停止,返回结果列表,注意与filter的区别。
    j. odd 判断一个数是否为奇数,even判断一个数是否为偶数
Prelude> take 7 (repeat 6)
[6,6,6,6,6,6,6]
Prelude> take 17 (cycle "yukipedia")
"yukipediayukipedi" 
Prelude> [0.1,0.2..1]
[0.1,0.2,0.30000000000000004,0.4000000000000001,0.5000000000000001,0.6000000000000001,0.7000000000000001,0.8,0.9,1.0]
Prelude> [1,(-2)..(-20)]
[1,-2,-5,-8,-11,-14,-17,-20]

list comprehension

[f(x,y)|x<-set,y<-set,predicate(x,y),let <bindins> in <expressions>]
列表推导式自然是产生列表的咯
分别演示了自定义length函数(每次元素满足谓词,执行f)、取出大写字符(处理字符串)、不拆开嵌套列表而去除奇数(始终返回列表)

Prelude> [x * y | x<-[1,2,3], y<-[10,12,14],x*y>20]
[24,28,30,36,42]
Prelude> length' xs = sum [1|_<-xs]
Prelude> length' [1..20]
20
Prelude> removeNonUppercase st = [c|c<-st,c `elem`['A'..'Z']]
Prelude> removeNonUppercase "yuKiPEdiA"
"KPEA"
Prelude> let nestList = [[2,3,4,5],[6,7,8,9],[10,11,12,13,14]]
Prelude> [[x|x<-nL,even x]|nL<-nestList]
[[2,4],[6,8],[10,12,14]]

tuple

元组是异构的,并且长度固定,由括号括起,由逗号隔开 。长度为2的元组(序对,pair)与长度为3的元组(三元组,triple)被视为不同的类型。进一步,两个元组要类型相同,需要每一项的类型都彼此对应。毫无疑问,每个元组都可能是个独特的类型。正因为如此,允许单元素的list,却不允许单元素的tuple。单纯用括号包含单元素,最终也只是作为表达式得到单元素。空元组类型为()。

  1. fst取一个序对作为参数,返回其首项。snd返回其尾项。
  2. zip list list 返回交叉配对的一组序对
Prelude> zip [1..] ["yukino","yui","hiki"]
[(1,"yukino"),(2,"yui"),(3,"hiki")]

接下来演示一个实际问题,求三条边为1..10的整数,和为24的直角三角形。函数式一般思路:先去一个初始的集合并将其变形,随后持续地利用过滤条件缩小计算范围。

Prelude> let rightTriangles' = [(a,b,c)|c<-[1..10],a<-[1..c],b<-[a..c-1],a^2+b^2==c^2,a+b+c==24]
Prelude> rightTriangles' 
[(6,8,10)]

基本数据类型

a.Int为有界整数,Integer无界,效率低于Int
b.Float 单精点浮点数,Double双精点
c.Bool布尔值
d.Char 表示一个Unicode字符,一个字符由单引号括起,一组字符的列表即字符串
e.凡是类型首字母大写,()除外
f.Odering类型有GT,LT,EQ三种值,分别表示大于,小于,等于
g.String是[Char]的别名

类型推断

:t 命令接受任何合法的表达式,返回其类型。:: 读作“它的类型为”。 后面可能会有type constraint,一定会有参数类型,最后一个参数代表返回值。
对函数而言可以“静态类型检查”诸如factorial1 :: Integer -> Integer factorial1 n = sum[1..n]限制输入参数。
当对判断性质的运算符,如==,+,-,使用:t时,需要用(),如:t (==)。其实当中缀函数要作为参数或者前缀函数调用时,都需要用括号括起。可以中缀形式定义函数,通过反引号。

Prelude> :t "yukipedia"
"yukipedia" :: [Char]
Prelude> factorial n = product [1..n]
Prelude> :t factorial 
factorial :: (Num a, Enum a) => a -> a
Prelude> :t head
head :: [a] -> a

类型注解(type annotation)

编译器可以辨认出大部分表达式的类型,但有时需要提示具体的类型。类型注解跟在表达式后面,通过 :: 分隔,显式表达类型。

Prelude> read "True"
*** Exception: Prelude.read: no parse
Prelude> read "True"||False
True
Prelude> [read "True",False]
[True,False]
Prelude> (read "True",False)
(*** Exception: Prelude.read: no parse
Prelude> read "True"::Bool
True
Prelude> read "True"::Int
*** Exception: Prelude.read: no parse

类型变量(type variable)

形如head函数的类型判断中的a,a可以是任何类型,使用类型变量的函数被称为多态函数(polymorphic function)。命名上,类型变量可以使用多个字符,不过一般约定为单字符,如a,b,c,d...。另外不同字符的类型变量并非意味两者表示的类型一定不同。
=>左侧叫做类型约束(type constraint),暂时认为类型变量始终泛指,而类型约束提供了范围
多态常量(polymorphic constant)指类型约束后 (typeclass a)=> a 这个函数输入输出没有变化?所有的数都是多态常量

Prelude> :t 7.0
7.0 :: Fractional p => p
Prelude> :t 7
7 :: Num p => p

类型类(typeclass)

typeclass是一组函数的集合,type constraint => type variable->type variable->..->type variable,所有变量都有类型,如果该类型是某typeclass的instance,那么它必须实现该类型所描述的行为。typeclass是定义行为的接口。即instance(变量所属的类型)具备执行“描述的行为”的能力,typeclass为定义行为的接口
1.Eq类型类用于判可断相等性的类型,它的实例必须实现==和/=两个函数。
2.Ord类型类用于可比较大小的类型
3.Show类型类的实例为可以表示为字符串的类型
4.Read类型类与Show相反,将字符串转化为某类型
5.Enum类型类包含()、Bool、Char、Ordering、Int、Integer、Float、Double等类型(实例),可作为succ函数和pred函数的参数
6.Bounded类型类的实例类型可以通过maxBound和minBound得到其上限和下限,如果元组中的项的类型都属于Bounded类型类的实例,那么这个元组也属于Bounded的实例。
7.Num类型类的实例类型为Int、Integer、Float、Double等,只有属于Show和Eq的实例类型,才可以成为Num类型类的实例
8.Floating类型类仅包含Float和Double两种浮点类型
9.Integeral仅与整数有关,实例类型为Int和Integer
a.所有标准类型都是Eq类的实例(除与输入输出相关的类型和函数之外)
b.除函数以外,以上所有类型都是Ord,Read,Show的实例
c.typeclass含有多个类型作为实例,一个类型可以作为多个typeclass的实例。一个类型必须在成为某typeclass的实例后,才能成为另一个typeclas的实例

Prelude> :t fromIntegral 
fromIntegral :: (Integral a, Num b) => a -> b
Prelude> fromIntegral (3)+3.2
6.2
Prelude> 3 + 3.2
6.2
Prelude> (3 :: Int)+3.2

<interactive>:39:12: error:
    • No instance for (Fractional Int) arising from the literal ‘3.2’
    • In the second argument of ‘(+)’, namely ‘3.2’
      In the expression: (3 :: Int) + 3.2
      In an equation for ‘it’: it = (3 :: Int) + 3.2
Prelude> (3 :: Float)+3.2
6.2

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

推荐阅读更多精彩内容

  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,798评论 0 38
  • 《六项精进》 大纲,背诵1遍,共368遍 《 大学》诵读1遍,共228遍 其他经典 活法 日行一善,完成 日省一事...
    a92bbf37be2b阅读 165评论 0 0
  • 《大三小三》 隔壁家的孩子大三毕业了又去当了小三 《怦然心动》 要不是你说“我们”我不会怦然心动 《重量级》 记住...
    何鲸洛阅读 247评论 0 1
  • 我是从十万伤心的大山里走来的人 我扛着黑色的锄头 带着辛勤的思念 我一点点在爱你的路上耕耘 我在耕耘的时候背后被人...
    梵夜阅读 196评论 0 4
  • 琐事记8.6 前几天,母亲热得难受,晚上睡不着,她对我说,想要装个空调。我说,好的,我来支付空调的的费用。 第二天...
    小棕榈阅读 296评论 0 0