Learn Haskell(一)
Learn Haskell
这一系列博客是《Learn You a Haskell for Great Good》的读书笔记。
一句话介绍:Haskell是一门纯粹的函数式编程语言。至于什么是函数式编程?尽管网上也有很多关于函数式语言与指令式语言之间的区别与联系,但是没有实际使用过函数式编程语言的情况下,我也搞不清楚。因此,先从学习一门函数式编程语言开始吧。
1.安装Haskell
要开始使用Haskell其实很简单,只需要一个文本编辑器和一个Haskell的编译器。目前来说最流行的Haskell的编译器是Glasgow
Haskell Compiler(GHC),我使用的就是这样一个编译器。
一般来说,我们会安装Haskell
Platform,因为它不仅包含了Haskell编译器,还绑定了一下常用的库。Haskell的官方网站是:http://www.haskell.org/haskellwiki/Haskell不管是Windows版本、Linux版本、Unix版本都有。
我使用的是Ubuntu系统,使用apt-get
安装其实很简单,只需要一条命令就好啦:
sudo
apt-get install
haskell-platform
GHC不但可以编译Haskell脚本(.hs文件),也可以以交互式方式运行。要启动交互模式,在终端中输入:
ghci
这时,中断会输出一些信息:
GHCi,
version 7.4.1: http://www.haskell.org/ghc/ :? for help
Loading package
ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ...
done.
Loading package base ... linking ...
done.
Prelude>
如果在Haskell文件中定义了一些函数,可以在GHC交互式解析器中输入:
:l
myFunctions
来载入你定义的函数。
2.基本算数操作
算数操作基本上和Java等其他语言都比较类似,直接举几个例子:
Prelude>
2 + 3
5
Prelude> 2 * 3
6
Prelude> 2 - 3
-1
Prelude> 2
/ 3
0.6666666666666666
需要特别注意的事情是,在使用负数的时候,最好是使用括号,举个例子:
Prelude> 2
* -3
<interactive>:7:1:
Precedence parsing error
cannot mix `*' [infixl 7] and prefix `-' [infixl 6] in the same infix expression
3.布尔代数
Haskell的与、或、非其实也很直接,直接看例子:
Prelude> True
&& False
False
Prelude> True &&
True
True
Prelude> True || False
True
Prelude> not
False
True
判断是否相等、是否不等:
Prelude> 2 == 3
False
Prelude> 2 /=
3
True
实际上尽管我们没有提过函数,但是其实已经用到了函数,*
运算实际上是一个函数,它接收两个参数,上面那种形式叫做中缀函数,但是实际上大部分函数是以前缀函数的形式调用的,下面介绍几个:
Prelude>
succ 8
9
Prelude> max 7 8
8
Prelude> min 8
9
8
Prelude> div 9
2
4
5.函数需要注意的
这几个函数的作用非常明显。但是需要注意的是div
函数其实等价于Java语言中的/
运算符,小数部分是舍弃的。上面的函数我们也可以以中缀函数的形式调用,比如:
Prelude>
9 `div` 2
4
我们可以定义自己的函数,函数定义的格式如下:
函数名 =
函数代码
我们新建一个.hs文件,在其中定义一个函数:
doubleMe x = x *
2
输入:l file.hs
,在交互式解析器中加载你所定义的函数,这时,解析器会输出如下信息:
Prelude>
:l baby.hs
[1 of 1] Compiling Main ( baby.hs, interpreted )
Ok, modules
loaded: Main.
*Main>
接下来就可以使用你所定义的函数了:
*Main> doubleMe
2
4
在定义别的函数的时候可以使用已经定义的函数,例如:
doubleUs x y = x * 2 + y *
2
Haskell中也有if
表达式,但是与Java语言的if表达式有一些区别,我们先看一个例子:
doubleSmallNumber
x = if x > 100 then x else x *
2
这个函数的意思是,如果一个数小于等于100,就翻倍,否则保持不变。但是需要注意的是,Haskell中的else部分是必须有的。此外还需要注意的是,Haskell函数名的首字母必须小写。
如果函数没有参数,那么这样的函数在Haskell中叫做定义或者名称。这一点有点类似于Java中的变量,但是有非常重要的区别:Haskell中的定义一旦给出就不允许改变
6.List概述
Haskell中的List是一种比较均匀整齐的数据结构,之所以说它均匀整齐是因为其中的元素必须是相同类型的。List是被方括号包裹起来的:
*Main>
let nums = [1,2,3,4]
*Main>
nums
[1,2,3,4]
在GHCi中需要使用let
来定义一个List。List有很多操作,下面分别介绍。
List连接操作
使用++来连接两个List,直接看代码:
*Main>
nums ++
[5,6]
[1,2,3,4,5,6]
在Haskell中,字符串实际上就是列表,也可以使用++进行连接操作:
*Main>
"Hello," ++ " " ++ "World!"
"Hello,
World!"
可以使用:操作符将一个元素放到一个列表最前面:
*Main> 0 : [1,2,3]
[0,1,2,3]
可以使用!!使用索引访问List中的元素: *Main> [1,2,3,4] !!
3
4
索引号是从0开始的。
List比较大小
List比较大小的前提是List元素是可以比较的,比如说数字,比如说字母(按照字母表顺序)。比较的规则是以此比较每一个元素直到出现不同的元素,那第一个不同元素,元素大的List大:
*Main>
[1,2,3] < [1,2,4]
True
*Main> [1,2,3] <
[1,2,3]
False
*Main> [1,2,3] <
[1,2,2]
False
其他List操作
head:可以取出List的首元素;
tail:将List去掉首元素;
last:返回List的末尾元素;
init:返回除最后一个元素之前的所有元素构成的List
length:返回元素个数
null:判断List是否为空列表
take
n [...]:从列表中取出n个元素
drop n
[...]:忽略n个元素后返回List
maximum/minimum:取出最大/最小值
sum:所有元素求和
product:所有元素乘积
elem:判断元素是否在列表中
reverse:List倒置
*Main>
head [1,2,3]
1
*Main> tail [1,2,3]
[2,3]
*Main> last
[1,2,3]
3
*Main> init [1,2,3]
[1,2]
*Main> take 3
[1,2,3,4,5,6]
[1,2,3]
*Main> drop 3
[1,2,3,4,5,6]
[4,5,6]
*Main> length [1,2,3]
3
*Main> null
[]
True
*Main> reverse [1,2,3]
[3,2,1]
*Main> maximum
[1,2,3]
3
*Main> minimum [1,2,3]
1
*Main> sum
[1,2,3]
6
*Main> product [1,2,3]
6
*Main> 4 `elem` [1,2,3,5]
False
save me from myself