文章目录
各就各位预备
强迫症请看这里
GHCi的默认命令行提示符为Prelude> ,你可以按照以下设置来自定义你的命令行提示符
- 方式一:每次运行命令行提示符,事先输入`:set prompt “ghci> “
- 方式二:
- 在你的home目录下新建
.ghci
文件 - 用记事本打开此文件,输入
>:set prompt “ghci> “ - 保存并再次打开命令行,你可以看到变化了
- 在你的home目录下新建
简单运算
运算和其他语言基本没两样
1 2 3 4 5 6 7 8 9 |
ghci> 2+15 17 ghci> 49*100 4900 ghci> 1892-1472 420 ghci> 5/2 2.5 |
在表达式中隐式的包含了优先级,当然也可以用括号指定运算顺序
1 2 3 |
ghci> 50*100-4999 1 |
注意:只要表达式存在负数常量,就最好用括号括起来,否则会报错
一些常用符号 一
符号 | 意义 |
---|---|
&& | 逻辑与 |
|| | 逻辑或 |
not | 逻辑取反 |
== | 判断相等与否 |
/= | 判断不等与否 |
注意:==可以比较任何两个可以比较的值,两个类型必须相同,或者可以发生隐式转换
1.1 调用函数
中缀函数(infix function)
- 可能你没注意到,haskell中,*是一个函数. (笔者注:别闹,大家都是有经验的人了,c++里他是操作符,定义时不也和函数差不多么)
- 这种像三明治一样被两个参数夹在中间的叫做中缀函数
前缀函数(prefix function)
大部分函数属于前缀函数,即在调用时,先是函数名和一个空格,后跟参数列表(空格分隔)
一些示例
1 2 3 4 5 6 7 |
ghci> succ 8 9 ghci> max 9 10 10 ghci> min 100 101 100 |
在haskell中函数应用有最高的优先级
1 2 3 4 5 |
-- 因而 ghci> succ 9*10 -- 应写成 ghci> succ (9*10) |
以`function`的形式,可以将前缀函数当做中缀函数使用(是反引号)
1.2 小朋友的第一个函数
函数声明形式
1 2 |
doubleMe x=x+x |
- 等号前面的定义了函数的参数,等号后定义了函数的行为
- haskell中函数定义没有先后的顺序
- 可以在函数中调用其他的函数
如果否则语句
1 2 3 4 |
doubleMe x = if x > 20 then x else x*2 |
haskell中else部分是不可省略的
- haskell中,程序是一系列函数的集合:函数取数据作为参数,并将它们转为想要的结果
- haskell中每个函数都会返回一个结果,可以为其他函数所用
- 函数返回的是表达式而非语句
函数名与单引号
通常使用在函数名后加单引号的方式,表示这是某函数的严格求值(区别于惰性求值)形式,或者是稍经修改但区别不大的函数
其他注意
- haskell的函数名不能以大写字母开头
- 函数一旦被定义,就不能够被修改
- 没有参数的函数通常被称为定义或者名字
1.3 列表入门
haskell中的列表是一种储存多个相同类型元素的数据结构
1 2 3 4 |
ghci> let lostNumbers=[4,8,15,16,23,43] ghci> lostNumber {4,8,15,16,23,43} |
- 在haskell中,字符串这种数据结构其实就是包含单个字符的列表的语法糖而已
- ghci中,可以使用let关键字来定义一个常量,与写在脚本中用
:l
运行效果是等价的
1.3.1 拼接列表
- 使用
++
操作拼接两个列表 ++
会遍历左边一个列表- 使用”cons”运算符可以将一个元素插入列表头部,成本几乎为零
1 2 3 4 5 |
ghci> "12"++['3','4'] "1234" ghci> '0':"12" "012" |
- 有趣的是,
[1,2,3]
其实是1:2:3:[]
的语法糖
1.3.2 访问列表元素
1 2 3 |
ghci> [1,2,3]!!0 1 |
下标从零开始
1.3.3 嵌套列表
- 只要列表中的元素是可以比较的,则可以使用
>
,<
,<=
,>=
进行比较,比较原则和其他语言基本相同 - 非空列表总比空列表大
1.3.4 更多列表操作
- head返回首元素
- tail返回list[1:]
- last返回末尾元素
- init返回list[0:-1]
对于空列表操作会引发错误
- length 返回元素数
- null 返回是否为空的布尔值
- reverse返回一个列表的反转
take n <list>
返回列表的前n个元素组成的列表drop n <lsit>
删除前n个元素- maximum取列表的最大元素
- minimum取列表的最小元素
elem <element> <list>
可判断元素是否属于列表
1.4 德州区间
1 2 3 4 5 6 7 8 9 |
ghci> [1..20] [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,10] --注意,包括首尾,两端闭区间 ghci> ['x'..'z'] "xyz" ghci> [2,'x'..'z'] 'xz' -- 制定步长 |
无限列表
- 基于haskell惰性求值的特点,你也可以生成无穷列表,空出后范围即可
- 由于从首项开始,首元素不能为空
- cycle函数接受一个列表重复它生成一个无限列表
- repeat接受一个值作为参数,返回一个仅包含此值的无限列表
- 因为浮点数只支持有限的精度,在列表中使用务必小心
1.5 列表推导式
列表推导式(list comphrehension)和集合推导式(set comphrehension)类似
形式为
1 2 3 4 5 6 7 |
-- [操作|变量名<-[列表],谓词1,谓词2..] ghci> [x*2|x<-[1..10],x*2>=12] [12,14,16,18,20] ghci> let boomBangs xs =[if x<10 then "BOOM" else "BANG"|x<-xs,odd x] ghci> boomBangs[7..13] ["BOOM","BANG","BANG","BANG"] |
- 也可以从多个列表中取元素,用逗号分隔即可
- 可以用下划线_来绑定列表中元素的临时变量,表示我们并不关心他具体的值
- 在非GHCi下,列表推导式最好写成多行,尤其在嵌套情况下,可以保证可读性
1.6 元组
- 元组(tuple)允许我们将多个异构的值组成一个单一的值
- 元组长度是固定的
1 2 3 |
('a','c') (1,2,'3') |
以上都是元组
- 二元元组称为序对(pair),三元元组称为三元组(triple)
- 不同长度或者元素类型不同的元组会被视为不同类型
- 不能有单元素的元组,在haskell中,单元素元素和此元素类型一样,创建之没有意义
1.6.2 使用序对
- fst 返回一个序对的首项
- snd 返回一个序对的第二项
- zip 接受两个列表作为参数,生成一组序对的列表.他也是惰性的;并且在严格求值时,与python相同,他会在较短的结束时结束
1.6.3 找直角三角形
在haskell”懒惰的思路”(也就是函数式编程的一般思路)中:先取一个初始的集合,并将它变形,随后持续的利用过滤条件缩小计算范围,最终取得一个或多个最终解
GHCi中,不允许将定义或者表达式拆成多行