网站制作镇江,湖南网络工程职业技术学院,产品设计公司规划,wordpress转dzHaskell 语言
安装
因为我是 Windows 系统#xff0c;在这里下载一个 GHC for Win 后解压缩#xff0c;将解压缩后的目录中的 bin 添加到环境变量的 Path 中#xff0c;在命令行中输入 ghci 就可用交互式的了。
其中 bin 目录下有一个 runhaskell.exe 文件#xff0c;我…Haskell 语言
安装
因为我是 Windows 系统在这里下载一个 GHC for Win 后解压缩将解压缩后的目录中的 bin 添加到环境变量的 Path 中在命令行中输入 ghci 就可用交互式的了。
其中 bin 目录下有一个 runhaskell.exe 文件我们对一个后缀为 .hs 的文件应用这个可执行文件后就能写下面的代码了而不是在 ghci 中交互虽然那样学习更方便。
学习
四则运算
值得一提的是除法我们可以写出如下 main 函数并打印结果如
main do print (5 / 2)结果为 2.5 而不是 Cpp 中的 2 如果我们需要欧几里得除法则可以这样写
main do print (5 div 2) -- div 5 2 也是一样的结果为 2 而取模也不是通常的 % 符号而是
main do print (5 mod 2) -- mod 5 2 也是一样的布尔值
用 True 和 False 表示用 not 表示取反 表示逻辑与 || 表示逻辑或如
main dolet c 10if not (c 11)then putStr c 10else putStr c 11需要注意括号的位置基本上我们可以认为 not 是一个函数。
比较两个数
main dolet c 10if 5 / cthen putStr c not eqaul to 5else putStr c is 5注意这里的不等于使用的是 a / b 而不是 a ! b 而等于则为 a b 与其他语言是类似的。
一些基本函数
main do print (succ 8) -- 9main do print (min 10 11) -- 10main do print (max 10 11) -- 11函数的一些顺序有下面这个例子
main do print (succ 9 max 5 4 1)这等价于
main do print ((succ 9) (max 5 4) 1)编写自己的函数
doubleMe x x x
main doprint (doubleMe 9) -- 18squareMe x x * x
main doprint (squareMe 9) -- 81当然也可以用小数调用这些函数如
doubleMe x x x
main doprint (doubleMe 9.1) -- 18.2也就是说我们写的函数实际上是一个泛型的函数这很棒对于限制类型后面会提到。
多参数的函数
addxy x y x y
main doprint (addxy 7 8) -- 15带有 if 的函数
plusOne x if x 0 then x 1 else -1
main doprint (plusOne 1)print (plusOne 0)当然我们可以调整一些缩进写成
plusOne x if x 0then x 1else -1main doprint (plusOne 1)print (plusOne 0)这样使得代码更具有可读性。
list
我不清楚是否应该称呼其为数组我们可以写出这样的代码
main dolet c [1,2,3,4]print c -- [1,2,3,4]而我们常用的字符串如 abc 实际上为 [a,b,c] 的语法糖这与在 C 语言中有点类似也就是说
main doprint (abc [a,b,c]) -- True是毫无疑问的。
对于 list 拼接也显得很自然有
c [1,2,3] [2,3,4]
main doprint c -- [1,2,3,2,3,4]也有这样的拼接方法如
a 10
b [1,2,3]
main doprint (a : b) -- [10,1,2,3]下标访问在 C 语言中我们常常会这样写
#include stdio.h
int main(void) {int a[10];printf(%d, a[1]); // 未初始化值可能为随机return 0;
}而在 Haskell 中则是
a abcdefg
main doputChar (a !! 2) -- c我们发现其索引开始也是 0 这与一般的习惯很符合。
值得注意的是 list 之间也可以通过 、 、 、 比较结果好像为字典序但一般很少用到。
head 函数只取首个元素
c [1,2,3,4,5]
main doprint (head c) -- 1tail 函数为除了首个元素的其余元素的 list
c [1,2,3,4,5]
main doprint (tail c) -- [2,3,4,5]last 函数为最后一个元素
c [1,2,3,4,5]
main doprint (last c) -- 5init 函数为除了最后一个元素的其余元素的 list
c [1,2,3,4,5]
main doprint (last c) -- [1,2,3,4]注意 head 不能应用于空的 list 其余函数我没有测试。
length 函数返回 list 的长度
main doprint (length [1,2,3]) -- 3print (length []) -- 0null 函数返回一个布尔值表示 list 是否为空
main doprint (null []) -- Trueprint (null [1]) -- Falsereverse 函数返回一个翻转的 list
c [1,2,3]
main doprint (reverse c) -- [3,2,1]上面所说的函数全都是一个参数的函数且参数都为 list 下面的函数为两个参数具体看示例为
take 函数表示截取前几个元素组成新的 list
c [1,2,3,4,5]
main doprint (take 3 c) -- [1,2,3]print (take 0 c) -- []print (take 8 c) -- [1,2,3,4,5]drop 函数表示丢弃前几个元素组成新的 list
c [1,2,3,4,5]
main doprint (drop 3 c) -- [4,5]print (drop 0 c) -- [1,2,3,4,5]print (drop 100 c) -- []maximum 函数与 minimum 函数想必不必多说
c [1,2,3,4,5]
main doprint (maximum c) -- 5print (minimum c) -- 1sum 函数返回和
c [1,2,3]
main doprint (sum c) -- 6product 函数返回乘积
c [1,2,3]
main doprint (product c) -- 6elem 函数告诉我们这个元素是否在 list 中
c [1,2,3]
main doprint (1 elem c) -- Trueprint (-1 elem c) -- False通常用一个中缀表达式来写当然也可以写作 elem 1 c 因为更自然与之前的 div 和 mod 是类似的。
范围的 list 可以这样写
main doprint [1..5] -- [1,2,3,4,5]print [2,4..10] -- [2,4,6,8,10]print [3,6..20] -- [3,6,9,12,15,18]但是不能写 [5..1] 而必须写 [5,4..1] 我们可以理解为等差数列前两项以及最后一项但小数的时候不同
main doprint [0.1,0.3 .. 1] -- [0.1,0.3,0.5,0.7,0.8999999999999999,1.0999999999999999]cycle 函数可以将一个东西无限制的拼接如
main doprint (take 10 (cycle [1,2,3])) -- [1,2,3,1,2,3,1,2,3,1]于是我们只能用 take 函数将其取出部分。
repeat 函数则有
main doprint (take 10 (repeat 5)) -- [5,5,5,5,5,5,5,5,5,5]也有更方便的函数 replicate 可以做到
main doprint (replicate 3 10) -- [10,10,10]接下来是一个很厉害的工具可以制作我们想要的 list 形态例如我想要 {x∣0≤x≤20,xmod31,x∈Z}\{x\mid 0\leq x\leq 20,x\bmod 31,x\in\mathbb{Z}\}{x∣0≤x≤20,xmod31,x∈Z} 的 list 可以写
main doprint [x | x - [0..20], x mod 3 1]这甚至与数学中很类似。
我们也可以写函数接收一个 list 返回出想要的 list 如
weWant xs [x | x - xs, odd x]
main doprint (weWant [0,1,7,9]) -- [1,7,9]上面用到了函数 odd 同样的也有 even 。
不止如此我们也可以写出
prodEachElem xs ys [x * y | x - xs, y - ys]
main doprint (prodEachElem [1,2,3] [4,5,6]) -- [4,10,18]用数学表达则为 x{1,2,3},y{4,5,6},z{ab∣a∈x,b∈y}x\{1,2,3\},y\{4,5,6\},z\{ab\mid a\in x,b\in y\}x{1,2,3},y{4,5,6},z{ab∣a∈x,b∈y} 很自然。
回顾之前的函数 length 我们可以用 sum 写一个自己的版本为
length x sum [1 | _ - x]
main doprint (length []) -- 0print (length [1,2,3]) -- 3他可以正常的工作其中下划线 _ 代表我们并不关心这个是什么。
tuple
中文一般为元组。元组一般为 (a,b) 这样的形式。
fst 函数返回元组中的首个元素而 snd 返回第二个。
main doprint (fst (1,WWW)) -- 1print (snd (2,WWWA)) -- WWWA有一个很酷的函数为 zip 可以制作元组如
main doprint (zip [1,2,3] [A,B,C]) -- [(1,A),(2,B),(3,C)]print (zip [1..3] [A,B,C]) -- [(1,A),(2,B),(3,C)]print (zip [1..] [A,B]) -- [(1,A),(2,B)]可以看到是以 length 较短的标准制作的这样的话写出 [1..] 这样看似无穷多的 list 也变得合理了惰性。
当然元组也远远不止两个元素也可以写出
d [(a,b,c) | a - [1,3..10], b - [2,4..7], c - [7,11..18]]
main doprint d注意这里并不是 zip 函数所以不要写无穷无尽的我们可以将这里视为三重的循环体。刚刚出了事故我的电脑死机了看来这个编译器会一丝不苟的执行下去呢并没有检测是否会造成死循环。
类型
参考资料
[1] http://learnyouahaskell.com/chapters