Haskell学习-函数式编程初探 (2)

let in
let in 表达式,let 中绑定的名字仅对 in 部分可见。

-- 圆柱体面积 cylinder r h = let sideArea = 2 * pi * r * h topArea = pi * r ^2 in sideArea + 2 * topArea

递归

我们使用递归来实现斐波那契数列和快速排序,haskell写的快速排序是我见过的最容易理解的版本了,专门为解决数学问题而生的 haskell 在解决算法和数据结构方面果然是不同凡响。

-- 斐波那契数列 fab 1 = 1 fab 2 = 1 fab n = fab (n-1) + fab (n-2) -- 快速排序 quicksort [] = [] quicksort (x:xs) = let smallerSorted = quicksort [a | a <- xs, a <= x] biggerSorted = quicksort [a | a <- xs, a > x] in smallerSorted ++ [x] ++ biggerSorted

尾递归实现常用的map和filter函数

[] 表示空列表

_ 匹配的是任意值。

(x:xs) 非常有用的列表匹配模式,x表示第一项,xs表示除去第一项之后的部分。使用(x:xs)可以方便的实现尾递归

-- map map' f [] = [] map' f (x:xs) = f x : map' f xs -- filter filter' _ []= [] -- _代表任意值 filter' f (x:xs) | f x = x : filter' f xs | otherwise = filter' f xs

数据类型

了解了haskell基本语法后,我们再进一步了解haskell基本数据类型

:type 获取任何表达式的类型,可以用简写形式 :t

基本数据类型

Int 表示整数

Integer 也是整数,但表示的是无界的,所以可以表示非常大的数

Float 表示单精度的浮点数

Double 表示双精度的浮点数

Bool 表示布尔值,它只有两种值:True 和 False

Char 表示一个字符。一个字符由单引号括起,一组字符的 List 即为字符串

List 列表中所有的项都必须是同一类型。

Tuple 的类型取决于它的长度及其项的类型。

:t 1 -- Number 1 :: Num p => p :t 1::Integer 1::Integer :: Integer :t 1::Float 1::Float :: Float :t False -- Bool False :: Bool :t 'c' --字符 'c' :: Char :t "hello" -- 字符串 "hello" :: [Char] :t [1,2,3] -- 列表list [1,2,3] :: Num a => [a] :t [("hi",1),("there",2)] -- Tuple [("hi",1),("there",2)] :: Num b => [([Char], b)]

1::Integer 表示直接指定类型,如果不指定编译器会自动推导出类型,数字类型会推导出Number类型,它包括Int,Integer,Float,Double

[Char]String 表示的都是字符串类型

[1,2,3] :: Num a => [a] 列表中的 a 表示任意类型,意思你可以是Bool,Stirng,Int等等

[("hi",1),("there",2)] 这就是Tuple类型,列表里面的每个项都用 () 包起来,其中的每个项的元素数据类型必须相同,每个tuple中元素个数必须相等,但是每个tuple中的项可以不同类型,比如 ("hi",1) 中一个是字符串,一个是Int。

函数也有类型,定义函数的时候,加上参数的类型和输出类型是好习惯。

&&、||、not 表示与或非逻辑

== 表示等于

/= 表示不等于

++ 连接列表,相当于concat

a, b这种类型参数,表示可以传入任何类型。

(Num a, Num p, Ord a) => a -> p=> 之前表示的是类型约束,这里的 a 限定只能是 Num 类型和 Ord 类型。Num表示数字类型,Ord则表示可比较大小的型别,包含如下三种型别之一:GT, LT, EQ。

:t head -- 取列表第一项的函数 head :: [a] -> a :t sign -- sign函数 sign :: (Num a, Num p, Ord a) => a -> p :t (==) -- 是否相等 (==) :: Eq a => a -> a -> Bool :t (++) -- 列表连接函数 (++) :: [a] -> [a] -> [a] -- 执行 sign 2 > 1 head [3,2,1] > 3 "abc" == "bbc" > False "hello " ++ "world" > "hello world"

List 和 List comprehension

列表常用的函数
null 列表是否为空
length 返回列表长度
head 返回列表第一个元素
tail 返回列表除第一个元素以后的所有元素
last 返回列表最后一个元素
init 返回列表除最后一个元素之前的所有元素
take n 返回列表前n个元素
drop n 丢弃列表前n个元素
maximum 返回最大的元素
minimum 返回最小的元素
sum 返回元素的和
elem 元素是否包含于列表

list range
方便的range,尾递归加上list range,你真的还需要命令式语言中的循环语句吗?

[1..10] -- 1到10的列表 > [1,2,3,4,5,6,7,8,9,10] ['a'..'z'] -- a到z的字母字符串 > "abcdefghijklmnopqrstuvwxyz" take 10 [1,3..] -- 前10个奇数 > [1,3,5,7,9,11,13,15,17,19] take 10 (cycle[1,2,3]) -- 取前10的[1,2,3]序列 > [1,2,3,1,2,3,1,2,3,1] take 5 $ repeat 3 -- 取前5项的3序列 > [3,3,3,3,3] replicate 5 10 -- 相比 take repeat更方便的用法 > [10,10,10,10,10]

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpzdzz.html